10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2004 Google Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef HAVE_CONFIG_H
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <config.h>
300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef HAVE_WEBRTC_VOICE
330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/webrtc/webrtcvoiceengine.h"
350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <algorithm>
370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <cstdio>
380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <string>
390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <vector>
400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
41cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/media/base/audiorenderer.h"
42cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/media/base/constants.h"
43cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/media/base/streamparams.h"
44cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/media/base/voiceprocessor.h"
45cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/media/webrtc/webrtcvoe.h"
462a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/base64.h"
472a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/byteorder.h"
482a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/common.h"
492a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/helpers.h"
502a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/logging.h"
512a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/stringencode.h"
522a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/stringutils.h"
535528070a0c76057a000b877fc56ca4180ad2087bmallinath@webrtc.org#include "webrtc/common.h"
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "webrtc/modules/audio_processing/include/audio_processing.h"
555462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org#include "webrtc/video_engine/include/vie_network.h"
560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef WIN32
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <objbase.h>  // NOLINT
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket {
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstruct CodecPref {
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const char* name;
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int clockrate;
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int channels;
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int payload_type;
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool is_multi_rate;
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const CodecPref kCodecPrefs[] = {
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "OPUS",   48000,  2, 111, true },
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "ISAC",   16000,  1, 103, true },
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "ISAC",   32000,  1, 104, true },
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "CELT",   32000,  1, 109, true },
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "CELT",   32000,  2, 110, true },
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "G722",   16000,  1, 9,   false },
780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "ILBC",   8000,   1, 102, false },
790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "PCMU",   8000,   1, 0,   false },
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "PCMA",   8000,   1, 8,   false },
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "CN",     48000,  1, 107, false },
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "CN",     32000,  1, 106, false },
830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "CN",     16000,  1, 105, false },
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "CN",     8000,   1, 13,  false },
850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "red",    8000,   1, 127, false },
860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  { "telephone-event", 8000, 1, 126, false },
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// For Linux/Mac, using the default device is done by specifying index 0 for
900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// VoE 4.0 and not -1 (which was the case for VoE 3.5).
910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// On Windows Vista and newer, Microsoft introduced the concept of "Default
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Communications Device". This means that there are two types of default
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// devices (old Wave Audio style default and Default Communications Device).
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// On Windows systems which only support Wave Audio style default, uses either
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// -1 or 0 to select the default device.
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// On Windows systems which support both "Default Communication Device" and
1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// old Wave Audio style default, use -1 for Default Communications Device and
1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// -2 for Wave Audio style default, which is what we want to use for clips.
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// It's not clear yet whether the -2 index is handled properly on other OSes.
1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef WIN32
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDefaultAudioDeviceId = -1;
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDefaultSoundclipDeviceId = -2;
1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else
1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDefaultAudioDeviceId = 0;
1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const char kIsacCodecName[] = "ISAC";
1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const char kL16CodecName[] = "L16";
1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Codec parameters for Opus.
1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kOpusMonoBitrate = 32000;
1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Parameter used for NACK.
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// This value is equivalent to 5 seconds of audio data at 20 ms per packet.
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kNackMaxPackets = 250;
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kOpusStereoBitrate = 64000;
1197162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org// draft-spittka-payload-rtp-opus-03
1207162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org// Opus bitrate should be in the range between 6000 and 510000.
1217162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.orgstatic const int kOpusMinBitrate = 6000;
1227162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.orgstatic const int kOpusMaxBitrate = 510000;
123ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org
12480303b162fe139828d0661df23e03f09126508acwu@webrtc.org// Default audio dscp value.
12580303b162fe139828d0661df23e03f09126508acwu@webrtc.org// See http://tools.ietf.org/html/rfc2474 for details.
12680303b162fe139828d0661df23e03f09126508acwu@webrtc.org// See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00
1272a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgstatic const rtc::DiffServCodePoint kAudioDscpValue = rtc::DSCP_EF;
1287162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
129ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org// Ensure we open the file in a writeable path on ChromeOS and Android. This
130ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org// workaround can be removed when it's possible to specify a filename for audio
131ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org// option based AEC dumps.
1327162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org//
1337162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org// TODO(grunell): Use a string in the options instead of hardcoding it here
1347162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org// and let the embedder choose the filename (crbug.com/264223).
1357162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org//
136ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org// NOTE(ajm): Don't use hardcoded paths on platforms not explicitly specified
137ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org// below.
138ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org#if defined(CHROMEOS)
1397162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.orgstatic const char kAecDumpByAudioOptionFilename[] = "/tmp/audio.aecdump";
140ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org#elif defined(ANDROID)
141ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.orgstatic const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump";
1427162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org#else
1437162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.orgstatic const char kAecDumpByAudioOptionFilename[] = "audio.aecdump";
1447162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org#endif
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Dumps an AudioCodec in RFC 2327-ish format.
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic std::string ToString(const AudioCodec& codec) {
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::stringstream ss;
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ss << codec.name << "/" << codec.clockrate << "/" << codec.channels
1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org     << " (" << codec.id << ")";
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ss.str();
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic std::string ToString(const webrtc::CodecInst& codec) {
1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::stringstream ss;
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ss << codec.plname << "/" << codec.plfreq << "/" << codec.channels
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org     << " (" << codec.pltype << ")";
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ss.str();
1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1602a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgstatic void LogMultiline(rtc::LoggingSeverity sev, char* text) {
1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const char* delim = "\r\n";
1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (char* tok = strtok(text, delim); tok; tok = strtok(NULL, delim)) {
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_V(sev) << tok;
1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Severity is an integer because it comes is assumed to be from command line.
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic int SeverityToFilter(int severity) {
1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int filter = webrtc::kTraceNone;
1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (severity) {
1712a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    case rtc::LS_VERBOSE:
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      filter |= webrtc::kTraceAll;
1732a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    case rtc::LS_INFO:
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      filter |= (webrtc::kTraceStateInfo | webrtc::kTraceInfo);
1752a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    case rtc::LS_WARNING:
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      filter |= (webrtc::kTraceTerseInfo | webrtc::kTraceWarning);
1772a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    case rtc::LS_ERROR:
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      filter |= (webrtc::kTraceError | webrtc::kTraceCritical);
1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return filter;
1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic bool IsCodecMultiRate(const webrtc::CodecInst& codec) {
1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < ARRAY_SIZE(kCodecPrefs); ++i) {
1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (_stricmp(kCodecPrefs[i].name, codec.plname) == 0 &&
1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        kCodecPrefs[i].clockrate == codec.plfreq) {
1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return kCodecPrefs[i].is_multi_rate;
1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return false;
1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1937587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.orgstatic bool IsTelephoneEventCodec(const std::string& name) {
1947587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  return _stricmp(name.c_str(), "telephone-event") == 0;
1957587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org}
1967587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org
1977587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.orgstatic bool IsCNCodec(const std::string& name) {
1987587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  return _stricmp(name.c_str(), "CN") == 0;
1997587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org}
2007587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org
2017587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.orgstatic bool IsRedCodec(const std::string& name) {
2027587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  return _stricmp(name.c_str(), "red") == 0;
2037587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org}
2047587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic bool FindCodec(const std::vector<AudioCodec>& codecs,
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      const AudioCodec& codec,
2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      AudioCodec* found_codec) {
2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<AudioCodec>::const_iterator it = codecs.begin();
2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != codecs.end(); ++it) {
2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (it->Matches(codec)) {
2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (found_codec != NULL) {
2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        *found_codec = *it;
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return true;
2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return false;
2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
219cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org
2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic bool IsNackEnabled(const AudioCodec& codec) {
2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack,
2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                              kParamValueEmpty));
2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
225cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org// Gets the default set of options applied to the engine. Historically, these
226cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org// were supplied as a combination of flags from the channel manager (ec, agc,
227cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org// ns, and highpass) and the rest hardcoded in InitInternal.
228cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.orgstatic AudioOptions GetDefaultEngineOptions() {
229cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  AudioOptions options;
230cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  options.echo_cancellation.Set(true);
231cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  options.auto_gain_control.Set(true);
232cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  options.noise_suppression.Set(true);
233cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  options.highpass_filter.Set(true);
234cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  options.stereo_swapping.Set(false);
235cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  options.typing_detection.Set(true);
236cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  options.conference_mode.Set(false);
237cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  options.adjust_agc_delta.Set(0);
238cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  options.experimental_agc.Set(false);
239cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  options.experimental_aec.Set(false);
24070022fa5eb218ec690774cc4a74558699a79600asergeyu@chromium.org  options.experimental_ns.Set(false);
241cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  options.aec_dump.Set(false);
242cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  return options;
243cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org}
2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass WebRtcSoundclipMedia : public SoundclipMedia {
2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org public:
2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  explicit WebRtcSoundclipMedia(WebRtcVoiceEngine *engine)
2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      : engine_(engine), webrtc_channel_(-1) {
2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    engine_->RegisterSoundclip(this);
2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual ~WebRtcSoundclipMedia() {
2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    engine_->UnregisterSoundclip(this);
2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (webrtc_channel_ != -1) {
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // We shouldn't have to call Disable() here. DeleteChannel() should call
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // StopPlayout() while deleting the channel.  We should fix the bug
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // inside WebRTC and remove the Disable() call bellow.  This work is
2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // tracked by bug http://b/issue?id=5382855.
2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      PlaySound(NULL, 0, 0);
2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      Disable();
2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (engine_->voe_sc()->base()->DeleteChannel(webrtc_channel_)
2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          == -1) {
2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG_RTCERR1(DeleteChannel, webrtc_channel_);
2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool Init() {
26962fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org    if (!engine_->voe_sc()) {
27062fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org      return false;
27162fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org    }
27297fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org    webrtc_channel_ = engine_->CreateSoundclipVoiceChannel();
2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (webrtc_channel_ == -1) {
2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR0(CreateChannel);
2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool Enable() {
2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (engine_->voe_sc()->base()->StartPlayout(webrtc_channel_) == -1) {
2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR1(StartPlayout, webrtc_channel_);
2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool Disable() {
2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (engine_->voe_sc()->base()->StopPlayout(webrtc_channel_) == -1) {
2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR1(StopPlayout, webrtc_channel_);
2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual bool PlaySound(const char *buf, int len, int flags) {
2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // The voe file api is not available in chrome.
2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!engine_->voe_sc()->file()) {
2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Must stop playing the current sound (if any), because we are about to
3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // modify the stream.
3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (engine_->voe_sc()->file()->StopPlayingFileLocally(webrtc_channel_)
3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        == -1) {
3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR1(StopPlayingFileLocally, webrtc_channel_);
3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (buf) {
3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      stream_.reset(new WebRtcSoundclipStream(buf, len));
3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      stream_->set_loop((flags & SF_LOOP) != 0);
3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      stream_->Rewind();
3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Play it.
3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (engine_->voe_sc()->file()->StartPlayingFileLocally(
3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          webrtc_channel_, stream_.get()) == -1) {
3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG_RTCERR2(StartPlayingFileLocally, webrtc_channel_, stream_.get());
3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG(LS_ERROR) << "Unable to start soundclip";
3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        return false;
3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      stream_.reset();
3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int GetLastEngineError() const { return engine_->voe_sc()->error(); }
3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org private:
3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  WebRtcVoiceEngine *engine_;
3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int webrtc_channel_;
3322a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::scoped_ptr<WebRtcSoundclipStream> stream_;
3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgWebRtcVoiceEngine::WebRtcVoiceEngine()
3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : voe_wrapper_(new VoEWrapper()),
3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      voe_wrapper_sc_(new VoEWrapper()),
33862fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org      voe_wrapper_sc_initialized_(false),
3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      tracing_(new VoETraceWrapper()),
3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      adm_(NULL),
3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      adm_sc_(NULL),
3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      log_filter_(SeverityToFilter(kDefaultLogSeverity)),
3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      is_dumping_aec_(false),
3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      desired_local_monitor_enable_(false),
3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      tx_processor_ssrc_(0),
3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      rx_processor_ssrc_(0) {
3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Construct();
3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgWebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper,
3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                     VoEWrapper* voe_wrapper_sc,
3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                     VoETraceWrapper* tracing)
3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : voe_wrapper_(voe_wrapper),
3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      voe_wrapper_sc_(voe_wrapper_sc),
35562fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org      voe_wrapper_sc_initialized_(false),
3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      tracing_(tracing),
3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      adm_(NULL),
3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      adm_sc_(NULL),
3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      log_filter_(SeverityToFilter(kDefaultLogSeverity)),
3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      is_dumping_aec_(false),
3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      desired_local_monitor_enable_(false),
362aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      tx_processor_ssrc_(0),
363aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      rx_processor_ssrc_(0) {
364aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  Construct();
365aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
366aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
367aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgvoid WebRtcVoiceEngine::Construct() {
368aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  SetTraceFilter(log_filter_);
369aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  initialized_ = false;
370aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
371aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  SetTraceOptions("");
372aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (tracing_->SetTraceCallback(this) == -1) {
373aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG_RTCERR0(SetTraceCallback);
374aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
375aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (voe_wrapper_->base()->RegisterVoiceEngineObserver(*this) == -1) {
376aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG_RTCERR0(RegisterVoiceEngineObserver);
377aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
378aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Clear the default agc state.
379aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  memset(&default_agc_config_, 0, sizeof(default_agc_config_));
380aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
381aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Load our audio codec list.
382aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  ConstructCodecs();
383aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
384aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Load our RTP Header extensions.
385aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  rtp_header_extensions_.push_back(
386aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      RtpHeaderExtension(kRtpAudioLevelHeaderExtension,
387aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                         kRtpAudioLevelHeaderExtensionDefaultId));
388aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  rtp_header_extensions_.push_back(
389aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
390aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                         kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
391aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  options_ = GetDefaultEngineOptions();
392aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
393aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
394aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgstatic bool IsOpus(const AudioCodec& codec) {
395aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return (_stricmp(codec.name.c_str(), kOpusCodecName) == 0);
396aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
397aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
398aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgstatic bool IsIsac(const AudioCodec& codec) {
399aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return (_stricmp(codec.name.c_str(), kIsacCodecName) == 0);
400aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
401aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
402aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// True if params["stereo"] == "1"
403aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgstatic bool IsOpusStereoEnabled(const AudioCodec& codec) {
40402632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org  int value;
40502632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org  return codec.GetParam(kCodecParamStereo, &value) && value == 1;
406aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
407aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
408ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org// TODO(minyue): Clamp bitrate when invalid.
409aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgstatic bool IsValidOpusBitrate(int bitrate) {
410aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return (bitrate >= kOpusMinBitrate && bitrate <= kOpusMaxBitrate);
411aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
412aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
413aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// Returns 0 if params[kCodecParamMaxAverageBitrate] is not defined or invalid.
414aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// Returns the value of params[kCodecParamMaxAverageBitrate] otherwise.
415aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgstatic int GetOpusBitrateFromParams(const AudioCodec& codec) {
416aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  int bitrate = 0;
417aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (!codec.GetParam(kCodecParamMaxAverageBitrate, &bitrate)) {
418aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return 0;
419aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
420aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (!IsValidOpusBitrate(bitrate)) {
421aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_WARNING) << "Codec parameter \"maxaveragebitrate\" has an "
422aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                    << "invalid value: " << bitrate;
423aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return 0;
424aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
425aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return bitrate;
426aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
427aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
428621454260f22dfe3709f870c53df5c72e2417607buildbot@webrtc.org// Return true if params[kCodecParamUseInbandFec] == "1", false
42902632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org// otherwise.
43007617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.orgstatic bool IsOpusFecEnabled(const AudioCodec& codec) {
43102632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org  int value;
43202632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org  return codec.GetParam(kCodecParamUseInbandFec, &value) && value == 1;
43302632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org}
43407617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org
435ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org// Returns kOpusDefaultPlaybackRate if params[kCodecParamMaxPlaybackRate] is not
436ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org// defined. Returns the value of params[kCodecParamMaxPlaybackRate] otherwise.
437ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.orgstatic int GetOpusMaxPlaybackRate(const AudioCodec& codec) {
438ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  int value;
439ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  if (codec.GetParam(kCodecParamMaxPlaybackRate, &value)) {
440ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org    return value;
441ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  }
442ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  return kOpusDefaultMaxPlaybackRate;
443ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org}
444ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org
445ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.orgstatic void GetOpusConfig(const AudioCodec& codec, webrtc::CodecInst* voe_codec,
446ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org                          bool* enable_codec_fec, int* max_playback_rate) {
447ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  *enable_codec_fec = IsOpusFecEnabled(codec);
448ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  *max_playback_rate = GetOpusMaxPlaybackRate(codec);
449ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org
450ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  // If OPUS, change what we send according to the "stereo" codec
451ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  // parameter, and not the "channels" parameter.  We set
452ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  // voe_codec.channels to 2 if "stereo=1" and 1 otherwise.  If
453ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  // the bitrate is not specified, i.e. is zero, we set it to the
454ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  // appropriate default value for mono or stereo Opus.
455ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org
456ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  // TODO(minyue): The determination of bit rate might take the maximum playback
457ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  // rate into account.
458ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org
459ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  if (IsOpusStereoEnabled(codec)) {
460ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org    voe_codec->channels = 2;
461ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org    if (!IsValidOpusBitrate(codec.bitrate)) {
462ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org      if (codec.bitrate != 0) {
463ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org        LOG(LS_WARNING) << "Overrides the invalid supplied bitrate("
464ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org                        << codec.bitrate
465ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org                        << ") with default opus stereo bitrate: "
466ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org                        << kOpusStereoBitrate;
467ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org      }
468ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org      voe_codec->rate = kOpusStereoBitrate;
469ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org    }
470ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  } else {
471ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org    voe_codec->channels = 1;
472ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org    if (!IsValidOpusBitrate(codec.bitrate)) {
473ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org      if (codec.bitrate != 0) {
474ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org        LOG(LS_WARNING) << "Overrides the invalid supplied bitrate("
475ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org                        << codec.bitrate
476ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org                        << ") with default opus mono bitrate: "
477ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org                        << kOpusMonoBitrate;
478ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org      }
479ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org      voe_codec->rate = kOpusMonoBitrate;
480ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org    }
481ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  }
482ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  int bitrate_from_params = GetOpusBitrateFromParams(codec);
483ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  if (bitrate_from_params != 0) {
484ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org    voe_codec->rate = bitrate_from_params;
485ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  }
486ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org}
487ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org
488aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgvoid WebRtcVoiceEngine::ConstructCodecs() {
489aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
490aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  int ncodecs = voe_wrapper_->codec()->NumOfCodecs();
491aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  for (int i = 0; i < ncodecs; ++i) {
492aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    webrtc::CodecInst voe_codec;
493aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (voe_wrapper_->codec()->GetCodec(i, voe_codec) != -1) {
494aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      // Skip uncompressed formats.
495aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      if (_stricmp(voe_codec.plname, kL16CodecName) == 0) {
496aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        continue;
497aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      }
498aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
499aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      const CodecPref* pref = NULL;
500aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      for (size_t j = 0; j < ARRAY_SIZE(kCodecPrefs); ++j) {
501aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        if (_stricmp(kCodecPrefs[j].name, voe_codec.plname) == 0 &&
502aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org            kCodecPrefs[j].clockrate == voe_codec.plfreq &&
503aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org            kCodecPrefs[j].channels == voe_codec.channels) {
504aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org          pref = &kCodecPrefs[j];
505aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org          break;
506aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        }
507aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      }
508aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
509aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      if (pref) {
510aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        // Use the payload type that we've configured in our pref table;
511aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        // use the offset in our pref table to determine the sort order.
512aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        AudioCodec codec(pref->payload_type, voe_codec.plname, voe_codec.plfreq,
513aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                         voe_codec.rate, voe_codec.channels,
514aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                         ARRAY_SIZE(kCodecPrefs) - (pref - kCodecPrefs));
515aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        LOG(LS_INFO) << ToString(codec);
516aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        if (IsIsac(codec)) {
517aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org          // Indicate auto-bandwidth in signaling.
518aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org          codec.bitrate = 0;
519aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        }
520aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        if (IsOpus(codec)) {
521aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org          // Only add fmtp parameters that differ from the spec.
522aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org          if (kPreferredMinPTime != kOpusDefaultMinPTime) {
523aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org            codec.params[kCodecParamMinPTime] =
5242a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                rtc::ToString(kPreferredMinPTime);
525aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org          }
526aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org          if (kPreferredMaxPTime != kOpusDefaultMaxPTime) {
527aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org            codec.params[kCodecParamMaxPTime] =
5282a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                rtc::ToString(kPreferredMaxPTime);
529aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org          }
530aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org          // TODO(hellner): Add ptime, sprop-stereo, stereo and useinbandfec
531aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org          // when they can be set to values other than the default.
532aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        }
533aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        codecs_.push_back(codec);
534aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      } else {
535aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        LOG(LS_WARNING) << "Unexpected codec: " << ToString(voe_codec);
536aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      }
537aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
538aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
539aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Make sure they are in local preference order.
540aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  std::sort(codecs_.begin(), codecs_.end(), &AudioCodec::Preferable);
541aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
542aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
543aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgWebRtcVoiceEngine::~WebRtcVoiceEngine() {
544aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  LOG(LS_VERBOSE) << "WebRtcVoiceEngine::~WebRtcVoiceEngine";
545aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (voe_wrapper_->base()->DeRegisterVoiceEngineObserver() == -1) {
546aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG_RTCERR0(DeRegisterVoiceEngineObserver);
547aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
548aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (adm_) {
549aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    voe_wrapper_.reset();
550aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    adm_->Release();
551aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    adm_ = NULL;
552aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
553aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (adm_sc_) {
554aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    voe_wrapper_sc_.reset();
555aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    adm_sc_->Release();
556aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    adm_sc_ = NULL;
557aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
558aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
559aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Test to see if the media processor was deregistered properly
560aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  ASSERT(SignalRxMediaFrame.is_empty());
561aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  ASSERT(SignalTxMediaFrame.is_empty());
562aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
563aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  tracing_->SetTraceCallback(NULL);
564aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
565aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
5662a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgbool WebRtcVoiceEngine::Init(rtc::Thread* worker_thread) {
567aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  LOG(LS_INFO) << "WebRtcVoiceEngine::Init";
568aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  bool res = InitInternal();
569aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (res) {
570aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_INFO) << "WebRtcVoiceEngine::Init Done!";
571aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  } else {
572aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_ERROR) << "WebRtcVoiceEngine::Init failed";
573aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    Terminate();
574aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
575aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return res;
576aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
577aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
578aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::InitInternal() {
579aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Temporarily turn logging level up for the Init call
580aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  int old_filter = log_filter_;
5812a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  int extended_filter = log_filter_ | SeverityToFilter(rtc::LS_INFO);
582aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  SetTraceFilter(extended_filter);
583aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  SetTraceOptions("");
584aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
585aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Init WebRtc VoiceEngine.
586aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (voe_wrapper_->base()->Init(adm_) == -1) {
587aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG_RTCERR0_EX(Init, voe_wrapper_->error());
588aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    SetTraceFilter(old_filter);
589aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return false;
590aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
591aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
592aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  SetTraceFilter(old_filter);
593aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  SetTraceOptions(log_options_);
594aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
595aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Log the VoiceEngine version info
596aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  char buffer[1024] = "";
597aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  voe_wrapper_->base()->GetVersion(buffer);
598aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  LOG(LS_INFO) << "WebRtc VoiceEngine Version:";
5992a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  LogMultiline(rtc::LS_INFO, buffer);
600aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
601aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Save the default AGC configuration settings. This must happen before
602aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // calling SetOptions or the default will be overwritten.
603aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (voe_wrapper_->processing()->GetAgcConfig(default_agc_config_) == -1) {
604aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG_RTCERR0(GetAgcConfig);
605aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return false;
606aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
607aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
608aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Set defaults for options, so that ApplyOptions applies them explicitly
609aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // when we clear option (channel) overrides. External clients can still
610aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // modify the defaults via SetOptions (on the media engine).
611aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (!SetOptions(GetDefaultEngineOptions())) {
612aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return false;
613aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
614aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
615aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Print our codec list again for the call diagnostic log
616aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
617aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  for (std::vector<AudioCodec>::const_iterator it = codecs_.begin();
618aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      it != codecs_.end(); ++it) {
619aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_INFO) << ToString(*it);
620aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
621aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
622aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Disable the DTMF playout when a tone is sent.
623aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // PlayDtmfTone will be used if local playout is needed.
624aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (voe_wrapper_->dtmf()->SetDtmfFeedbackStatus(false) == -1) {
625aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG_RTCERR1(SetDtmfFeedbackStatus, false);
626aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
627aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
628aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  initialized_ = true;
629aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return true;
630aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
631aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
632aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::EnsureSoundclipEngineInit() {
633aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (voe_wrapper_sc_initialized_) {
634aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return true;
635aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
636aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Note that, if initialization fails, voe_wrapper_sc_initialized_ will still
637aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // be false, so subsequent calls to EnsureSoundclipEngineInit will
638aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // probably just fail again. That's acceptable behavior.
639aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#if defined(LINUX) && !defined(HAVE_LIBPULSE)
640aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  voe_wrapper_sc_->hw()->SetAudioDeviceLayer(webrtc::kAudioLinuxAlsa);
641aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#endif
642aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
643aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Initialize the VoiceEngine instance that we'll use to play out sound clips.
644aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (voe_wrapper_sc_->base()->Init(adm_sc_) == -1) {
645aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG_RTCERR0_EX(Init, voe_wrapper_sc_->error());
646aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return false;
647aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
648aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
649aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // On Windows, tell it to use the default sound (not communication) devices.
650aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // First check whether there is a valid sound device for playback.
651aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // TODO(juberti): Clean this up when we support setting the soundclip device.
652aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#ifdef WIN32
653aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // The SetPlayoutDevice may not be implemented in the case of external ADM.
654aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // TODO(ronghuawu): We should only check the adm_sc_ here, but current
655aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // PeerConnection interface never set the adm_sc_, so need to check both
656aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // in order to determine if the external adm is used.
657aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (!adm_ && !adm_sc_) {
658aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    int num_of_devices = 0;
659aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (voe_wrapper_sc_->hw()->GetNumOfPlayoutDevices(num_of_devices) != -1 &&
660aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        num_of_devices > 0) {
661aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      if (voe_wrapper_sc_->hw()->SetPlayoutDevice(kDefaultSoundclipDeviceId)
662aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org          == -1) {
663aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        LOG_RTCERR1_EX(SetPlayoutDevice, kDefaultSoundclipDeviceId,
664aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                       voe_wrapper_sc_->error());
665aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        return false;
666aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      }
667aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    } else {
668aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG(LS_WARNING) << "No valid sound playout device found.";
669aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
670aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
671aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#endif
672aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  voe_wrapper_sc_initialized_ = true;
673aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  LOG(LS_INFO) << "Initialized WebRtc soundclip engine.";
674aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return true;
675aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
676aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
677aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgvoid WebRtcVoiceEngine::Terminate() {
678aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate";
679aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  initialized_ = false;
680aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
681aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  StopAecDump();
682aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
683aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (voe_wrapper_sc_) {
684aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    voe_wrapper_sc_initialized_ = false;
685aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    voe_wrapper_sc_->base()->Terminate();
686aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
687aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  voe_wrapper_->base()->Terminate();
688aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  desired_local_monitor_enable_ = false;
689aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
690aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
691aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgint WebRtcVoiceEngine::GetCapabilities() {
692aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return AUDIO_SEND | AUDIO_RECV;
693aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
694aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
695aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgVoiceMediaChannel *WebRtcVoiceEngine::CreateChannel() {
696aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  WebRtcVoiceMediaChannel* ch = new WebRtcVoiceMediaChannel(this);
697aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (!ch->valid()) {
698aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    delete ch;
699aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    ch = NULL;
700aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
701aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return ch;
702aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
703aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
704aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgSoundclipMedia *WebRtcVoiceEngine::CreateSoundclip() {
705aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (!EnsureSoundclipEngineInit()) {
706aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_ERROR) << "Unable to create soundclip: soundclip engine failed to "
707aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                  << "initialize.";
708aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return NULL;
709aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
710aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  WebRtcSoundclipMedia *soundclip = new WebRtcSoundclipMedia(this);
711aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (!soundclip->Init() || !soundclip->Enable()) {
712aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    delete soundclip;
713aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return NULL;
714aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
715aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return soundclip;
716aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
717aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
718aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::SetOptions(const AudioOptions& options) {
719aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (!ApplyOptions(options)) {
720aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return false;
721aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
722aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  options_ = options;
723aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return true;
724aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
725aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
726aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::SetOptionOverrides(const AudioOptions& overrides) {
727aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  LOG(LS_INFO) << "Setting option overrides: " << overrides.ToString();
728aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (!ApplyOptions(overrides)) {
729aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return false;
730aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
731aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  option_overrides_ = overrides;
732aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return true;
733aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
734aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
735aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::ClearOptionOverrides() {
736aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  LOG(LS_INFO) << "Clearing option overrides.";
737aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  AudioOptions options = options_;
738aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Only call ApplyOptions if |options_overrides_| contains overrided options.
739aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // ApplyOptions affects NS, AGC other options that is shared between
740aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // all WebRtcVoiceEngineChannels.
741aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (option_overrides_ == AudioOptions()) {
742aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return true;
743aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
744aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
745aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (!ApplyOptions(options)) {
746aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return false;
747aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
748aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  option_overrides_ = AudioOptions();
749aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return true;
750aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
751aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
752aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// AudioOptions defaults are set in InitInternal (for options with corresponding
753aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// MediaEngineInterface flags) and in SetOptions(int) for flagless options.
754aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
755aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  AudioOptions options = options_in;  // The options are modified below.
756aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // kEcConference is AEC with high suppression.
757aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  webrtc::EcModes ec_mode = webrtc::kEcConference;
758aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  webrtc::AecmModes aecm_mode = webrtc::kAecmSpeakerphone;
759aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog;
760aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  webrtc::NsModes ns_mode = webrtc::kNsHighSuppression;
761aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  bool aecm_comfort_noise = false;
762aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (options.aecm_generate_comfort_noise.Get(&aecm_comfort_noise)) {
763aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_VERBOSE) << "Comfort noise explicitly set to "
764aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                    << aecm_comfort_noise << " (default is false).";
765aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
766aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
767aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#if defined(IOS)
768aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // On iOS, VPIO provides built-in EC and AGC.
769aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  options.echo_cancellation.Set(false);
770aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  options.auto_gain_control.Set(false);
771aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#elif defined(ANDROID)
772aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  ec_mode = webrtc::kEcAecm;
773aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#endif
774aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
775aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#if defined(IOS) || defined(ANDROID)
776aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Set the AGC mode for iOS as well despite disabling it above, to avoid
777aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // unsupported configuration errors from webrtc.
778aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  agc_mode = webrtc::kAgcFixedDigital;
779aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  options.typing_detection.Set(false);
780aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  options.experimental_agc.Set(false);
781aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  options.experimental_aec.Set(false);
782aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  options.experimental_ns.Set(false);
783aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#endif
784aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
785aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  LOG(LS_INFO) << "Applying audio options: " << options.ToString();
786aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
787aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  webrtc::VoEAudioProcessing* voep = voe_wrapper_->processing();
788aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
789aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  bool echo_cancellation;
790aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (options.echo_cancellation.Get(&echo_cancellation)) {
791aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (voep->SetEcStatus(echo_cancellation, ec_mode) == -1) {
792aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG_RTCERR2(SetEcStatus, echo_cancellation, ec_mode);
793aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      return false;
794aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    } else {
795aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG(LS_VERBOSE) << "Echo control set to " << echo_cancellation
796aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                      << " with mode " << ec_mode;
797aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
798aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#if !defined(ANDROID)
799aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    // TODO(ajm): Remove the error return on Android from webrtc.
800aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (voep->SetEcMetricsStatus(echo_cancellation) == -1) {
801aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG_RTCERR1(SetEcMetricsStatus, echo_cancellation);
802aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      return false;
803aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
804aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#endif
805aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (ec_mode == webrtc::kEcAecm) {
806aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      if (voep->SetAecmMode(aecm_mode, aecm_comfort_noise) != 0) {
807aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        LOG_RTCERR2(SetAecmMode, aecm_mode, aecm_comfort_noise);
808aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        return false;
809aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      }
810aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
811aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
812aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
813aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  bool auto_gain_control;
814aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (options.auto_gain_control.Get(&auto_gain_control)) {
815aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (voep->SetAgcStatus(auto_gain_control, agc_mode) == -1) {
816aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG_RTCERR2(SetAgcStatus, auto_gain_control, agc_mode);
817aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      return false;
818aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    } else {
819aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG(LS_VERBOSE) << "Auto gain set to " << auto_gain_control
820aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                      << " with mode " << agc_mode;
821aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
822aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
823aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
824aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (options.tx_agc_target_dbov.IsSet() ||
825aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      options.tx_agc_digital_compression_gain.IsSet() ||
826aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      options.tx_agc_limiter.IsSet()) {
827aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    // Override default_agc_config_. Generally, an unset option means "leave
828aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    // the VoE bits alone" in this function, so we want whatever is set to be
829aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    // stored as the new "default". If we didn't, then setting e.g.
830aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    // tx_agc_target_dbov would reset digital compression gain and limiter
831aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    // settings.
832aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    // Also, if we don't update default_agc_config_, then adjust_agc_delta
833aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    // would be an offset from the original values, and not whatever was set
834aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    // explicitly.
835aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    default_agc_config_.targetLeveldBOv =
836aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        options.tx_agc_target_dbov.GetWithDefaultIfUnset(
837aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org            default_agc_config_.targetLeveldBOv);
838aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    default_agc_config_.digitalCompressionGaindB =
839aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        options.tx_agc_digital_compression_gain.GetWithDefaultIfUnset(
840aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org            default_agc_config_.digitalCompressionGaindB);
841aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    default_agc_config_.limiterEnable =
842aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        options.tx_agc_limiter.GetWithDefaultIfUnset(
843aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org            default_agc_config_.limiterEnable);
844aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (voe_wrapper_->processing()->SetAgcConfig(default_agc_config_) == -1) {
845aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG_RTCERR3(SetAgcConfig,
846aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                  default_agc_config_.targetLeveldBOv,
847aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                  default_agc_config_.digitalCompressionGaindB,
848aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                  default_agc_config_.limiterEnable);
849aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      return false;
850aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
851aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
852aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
853aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  bool noise_suppression;
854aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (options.noise_suppression.Get(&noise_suppression)) {
855aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (voep->SetNsStatus(noise_suppression, ns_mode) == -1) {
856aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG_RTCERR2(SetNsStatus, noise_suppression, ns_mode);
857aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      return false;
858aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    } else {
859aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG(LS_VERBOSE) << "Noise suppression set to " << noise_suppression
860aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                      << " with mode " << ns_mode;
861aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
862aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
863aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
864aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  bool highpass_filter;
865aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (options.highpass_filter.Get(&highpass_filter)) {
866aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_INFO) << "High pass filter enabled? " << highpass_filter;
867aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (voep->EnableHighPassFilter(highpass_filter) == -1) {
868aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG_RTCERR1(SetHighpassFilterStatus, highpass_filter);
869aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      return false;
870aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
871aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
872aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
873aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  bool stereo_swapping;
874aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (options.stereo_swapping.Get(&stereo_swapping)) {
875aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_INFO) << "Stereo swapping enabled? " << stereo_swapping;
876aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    voep->EnableStereoChannelSwapping(stereo_swapping);
877aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (voep->IsStereoChannelSwappingEnabled() != stereo_swapping) {
878aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG_RTCERR1(EnableStereoChannelSwapping, stereo_swapping);
879aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      return false;
880aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
881aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
882aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
883aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  bool typing_detection;
884aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (options.typing_detection.Get(&typing_detection)) {
885aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_INFO) << "Typing detection is enabled? " << typing_detection;
886aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (voep->SetTypingDetectionStatus(typing_detection) == -1) {
887aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      // In case of error, log the info and continue
888aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG_RTCERR1(SetTypingDetectionStatus, typing_detection);
889aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
890aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
891aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
892aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  int adjust_agc_delta;
893aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (options.adjust_agc_delta.Get(&adjust_agc_delta)) {
894aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_INFO) << "Adjust agc delta is " << adjust_agc_delta;
895aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (!AdjustAgcLevel(adjust_agc_delta)) {
896aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      return false;
897aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
898aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
899aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
900aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  bool aec_dump;
901aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (options.aec_dump.Get(&aec_dump)) {
902aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_INFO) << "Aec dump is enabled? " << aec_dump;
903aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (aec_dump)
904aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      StartAecDump(kAecDumpByAudioOptionFilename);
905aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    else
906aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      StopAecDump();
907aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
908aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
9095592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  webrtc::Config config;
9105592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org
9115592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  experimental_aec_.SetFrom(options.experimental_aec);
912aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  bool experimental_aec;
9135592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  if (experimental_aec_.Get(&experimental_aec)) {
9145592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org    LOG(LS_INFO) << "Experimental aec is enabled? " << experimental_aec;
9155592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org    config.Set<webrtc::DelayCorrection>(
9165592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org        new webrtc::DelayCorrection(experimental_aec));
9175592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  }
9185592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org
9195592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org#ifdef USE_WEBRTC_DEV_BRANCH
9205592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  experimental_ns_.SetFrom(options.experimental_ns);
9215592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  bool experimental_ns;
9225592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  if (experimental_ns_.Get(&experimental_ns)) {
9235592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org    LOG(LS_INFO) << "Experimental ns is enabled? " << experimental_ns;
9245592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org    config.Set<webrtc::ExperimentalNs>(
9255592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org        new webrtc::ExperimentalNs(experimental_ns));
9265592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  }
9275592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org#endif
9285592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org
9295592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  // We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine
9305592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  // returns NULL on audio_processing().
9315592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  webrtc::AudioProcessing* audioproc = voe_wrapper_->base()->audio_processing();
9325592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  if (audioproc) {
9335592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org    audioproc->SetExtraOptions(config);
9345592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  }
9355592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org
9365592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org#ifndef USE_WEBRTC_DEV_BRANCH
9375592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  bool experimental_ns;
9385592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org  if (options.experimental_ns.Get(&experimental_ns)) {
9395592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org    LOG(LS_INFO) << "Experimental ns is enabled? " << experimental_ns;
940aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    // We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine
941aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    // returns NULL on audio_processing().
942aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (audioproc) {
9435592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org      if (audioproc->EnableExperimentalNs(experimental_ns) == -1) {
9445592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org        LOG_RTCERR1(EnableExperimentalNs, experimental_ns);
9455592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org        return false;
9465592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org      }
9475592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org    } else {
9485592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org      LOG(LS_VERBOSE) << "Experimental noise suppression set to "
9495592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org                      << experimental_ns;
950aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
951aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
9525592deb0a050321bf2916fb300f490132dee99edbuildbot@webrtc.org#endif
953aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
954aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  uint32 recording_sample_rate;
955aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (options.recording_sample_rate.Get(&recording_sample_rate)) {
956aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_INFO) << "Recording sample rate is " << recording_sample_rate;
957aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (voe_wrapper_->hw()->SetRecordingSampleRate(recording_sample_rate)) {
958aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG_RTCERR1(SetRecordingSampleRate, recording_sample_rate);
959aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
960aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
961aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
962aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  uint32 playout_sample_rate;
963aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (options.playout_sample_rate.Get(&playout_sample_rate)) {
964aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_INFO) << "Playout sample rate is " << playout_sample_rate;
965aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (voe_wrapper_->hw()->SetPlayoutSampleRate(playout_sample_rate)) {
966aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG_RTCERR1(SetPlayoutSampleRate, playout_sample_rate);
967aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
968aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
969aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
970aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return true;
971aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
972aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
973aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::SetDelayOffset(int offset) {
974aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  voe_wrapper_->processing()->SetDelayOffsetMs(offset);
975aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (voe_wrapper_->processing()->DelayOffsetMs() != offset) {
976aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG_RTCERR1(SetDelayOffsetMs, offset);
977aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    return false;
978aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
979aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
980aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  return true;
981aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}
982aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
983aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgstruct ResumeEntry {
984aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  ResumeEntry(WebRtcVoiceMediaChannel *c, bool p, SendFlags s)
985aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      : channel(c),
986aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        playout(p),
987aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org        send(s) {
988aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
989aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
990aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  WebRtcVoiceMediaChannel *channel;
991aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  bool playout;
992aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  SendFlags send;
993aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org};
994aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
995aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// TODO(juberti): Refactor this so that the core logic can be used to set the
996aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// soundclip device. At that time, reinstate the soundclip pause/resume code.
997aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::SetDevices(const Device* in_device,
998aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org                                   const Device* out_device) {
999aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#if !defined(IOS)
10002a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  int in_id = in_device ? rtc::FromString<int>(in_device->id) :
1001aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      kDefaultAudioDeviceId;
10022a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  int out_id = out_device ? rtc::FromString<int>(out_device->id) :
1003aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      kDefaultAudioDeviceId;
1004aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // The device manager uses -1 as the default device, which was the case for
1005aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // VoE 3.5. VoE 4.0, however, uses 0 as the default in Linux and Mac.
1006aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#ifndef WIN32
1007aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (-1 == in_id) {
1008aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    in_id = kDefaultAudioDeviceId;
1009aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
1010aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (-1 == out_id) {
1011aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    out_id = kDefaultAudioDeviceId;
1012aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
1013aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#endif
1014aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
1015aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  std::string in_name = (in_id != kDefaultAudioDeviceId) ?
1016aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      in_device->name : "Default device";
1017aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  std::string out_name = (out_id != kDefaultAudioDeviceId) ?
1018aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      out_device->name : "Default device";
1019aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  LOG(LS_INFO) << "Setting microphone to (id=" << in_id << ", name=" << in_name
1020aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org            << ") and speaker to (id=" << out_id << ", name=" << out_name
1021aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org            << ")";
1022aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
1023aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // If we're running the local monitor, we need to stop it first.
1024aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  bool ret = true;
1025aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (!PauseLocalMonitor()) {
1026aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    LOG(LS_WARNING) << "Failed to pause local monitor";
1027aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    ret = false;
1028aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
1029aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
1030aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Must also pause all audio playback and capture.
1031aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  for (ChannelList::const_iterator i = channels_.begin();
1032aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org       i != channels_.end(); ++i) {
1033aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    WebRtcVoiceMediaChannel *channel = *i;
1034aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (!channel->PausePlayout()) {
1035aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG(LS_WARNING) << "Failed to pause playout";
1036aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      ret = false;
1037aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
1038aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (!channel->PauseSend()) {
1039aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG(LS_WARNING) << "Failed to pause send";
1040aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      ret = false;
1041aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
1042aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
1043aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org
1044aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  // Find the recording device id in VoiceEngine and set recording device.
1045aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (!FindWebRtcAudioDeviceId(true, in_name, in_id, &in_id)) {
1046aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    ret = false;
1047aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  }
1048aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org  if (ret) {
1049aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    if (voe_wrapper_->hw()->SetRecordingDevice(in_id) == -1) {
1050aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      LOG_RTCERR2(SetRecordingDevice, in_name, in_id);
1051aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org      ret = false;
1052aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org    }
10537663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org    webrtc::AudioProcessing* ap = voe()->base()->audio_processing();
10547663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org    if (ap)
10557663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org      ap->Initialize();
10560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Find the playout device id in VoiceEngine and set playout device.
10590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!FindWebRtcAudioDeviceId(false, out_name, out_id, &out_id)) {
10600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to find VoiceEngine device id for " << out_name;
10610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ret = false;
10620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (ret) {
10640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (voe_wrapper_->hw()->SetPlayoutDevice(out_id) == -1) {
106597fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org      LOG_RTCERR2(SetPlayoutDevice, out_name, out_id);
10660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ret = false;
10670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
10680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Resume all audio playback and capture.
10710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ChannelList::const_iterator i = channels_.begin();
10720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       i != channels_.end(); ++i) {
10730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    WebRtcVoiceMediaChannel *channel = *i;
10740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!channel->ResumePlayout()) {
10750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_WARNING) << "Failed to resume playout";
10760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ret = false;
10770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
10780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!channel->ResumeSend()) {
10790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_WARNING) << "Failed to resume send";
10800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ret = false;
10810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
10820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Resume local monitor.
10850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!ResumeLocalMonitor()) {
10860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to resume local monitor";
10870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ret = false;
10880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (ret) {
10910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_INFO) << "Set microphone to (id=" << in_id <<" name=" << in_name
10920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 << ") and speaker to (id="<< out_id << " name=" << out_name
10930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 << ")";
10940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ret;
10970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else
10980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
1099d1f631d5ec5c25dd0a63ed70d0ffa66037d8aa6awu@webrtc.org#endif  // !IOS
11000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::FindWebRtcAudioDeviceId(
11030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool is_input, const std::string& dev_name, int dev_id, int* rtc_id) {
11040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // In Linux, VoiceEngine uses the same device dev_id as the device manager.
1105d1f631d5ec5c25dd0a63ed70d0ffa66037d8aa6awu@webrtc.org#if defined(LINUX) || defined(ANDROID)
11060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *rtc_id = dev_id;
11070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
11080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else
11090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // In Windows and Mac, we need to find the VoiceEngine device id by name
11100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // unless the input dev_id is the default device id.
11110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (kDefaultAudioDeviceId == dev_id) {
11120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    *rtc_id = dev_id;
11130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
11140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Get the number of VoiceEngine audio devices.
11170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int count = 0;
11180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (is_input) {
11190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (-1 == voe_wrapper_->hw()->GetNumOfRecordingDevices(count)) {
11200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR0(GetNumOfRecordingDevices);
11210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
11220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
11230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
11240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (-1 == voe_wrapper_->hw()->GetNumOfPlayoutDevices(count)) {
11250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR0(GetNumOfPlayoutDevices);
11260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
11270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
11280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (int i = 0; i < count; ++i) {
11310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    char name[128];
11320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    char guid[128];
11330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (is_input) {
11340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      voe_wrapper_->hw()->GetRecordingDeviceName(i, name, guid);
11350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_VERBOSE) << "VoiceEngine microphone " << i << ": " << name;
11360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
11370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      voe_wrapper_->hw()->GetPlayoutDeviceName(i, name, guid);
11380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_VERBOSE) << "VoiceEngine speaker " << i << ": " << name;
11390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
11400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    std::string webrtc_name(name);
11420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (dev_name.compare(0, webrtc_name.size(), webrtc_name) == 0) {
11430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *rtc_id = i;
11440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return true;
11450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
11460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_WARNING) << "VoiceEngine cannot find device: " << dev_name;
11480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return false;
11490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
11500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::GetOutputVolume(int* level) {
11530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  unsigned int ulevel;
11540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (voe_wrapper_->volume()->GetSpeakerVolume(ulevel) == -1) {
11550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_RTCERR1(GetSpeakerVolume, level);
11560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
11570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *level = ulevel;
11590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
11600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::SetOutputVolume(int level) {
11630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(level >= 0 && level <= 255);
11640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (voe_wrapper_->volume()->SetSpeakerVolume(level) == -1) {
11650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_RTCERR1(SetSpeakerVolume, level);
11660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
11670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
11690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceEngine::GetInputLevel() {
11720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  unsigned int ulevel;
11730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return (voe_wrapper_->volume()->GetSpeechInputLevel(ulevel) != -1) ?
11740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      static_cast<int>(ulevel) : -1;
11750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::SetLocalMonitor(bool enable) {
11780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  desired_local_monitor_enable_ = enable;
11790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ChangeLocalMonitor(desired_local_monitor_enable_);
11800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::ChangeLocalMonitor(bool enable) {
11830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // The voe file api is not available in chrome.
11840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!voe_wrapper_->file()) {
11850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
11860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (enable && !monitor_) {
11880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    monitor_.reset(new WebRtcMonitorStream);
11890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (voe_wrapper_->file()->StartRecordingMicrophone(monitor_.get()) == -1) {
11900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR1(StartRecordingMicrophone, monitor_.get());
11910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Must call Stop() because there are some cases where Start will report
11920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // failure but still change the state, and if we leave VE in the on state
11930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // then it could crash later when trying to invoke methods on our monitor.
11940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      voe_wrapper_->file()->StopRecordingMicrophone();
11950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      monitor_.reset();
11960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
11970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
11980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (!enable && monitor_) {
11990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    voe_wrapper_->file()->StopRecordingMicrophone();
12000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    monitor_.reset();
12010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
12020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
12030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::PauseLocalMonitor() {
12060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ChangeLocalMonitor(false);
12070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::ResumeLocalMonitor() {
12100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ChangeLocalMonitor(desired_local_monitor_enable_);
12110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst std::vector<AudioCodec>& WebRtcVoiceEngine::codecs() {
12140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return codecs_;
12150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::FindCodec(const AudioCodec& in) {
12180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return FindWebRtcCodec(in, NULL);
12190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Get the VoiceEngine codec that matches |in|, with the supplied settings.
12220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::FindWebRtcCodec(const AudioCodec& in,
12230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                        webrtc::CodecInst* out) {
12240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int ncodecs = voe_wrapper_->codec()->NumOfCodecs();
12250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (int i = 0; i < ncodecs; ++i) {
12260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    webrtc::CodecInst voe_codec;
12270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (voe_wrapper_->codec()->GetCodec(i, voe_codec) != -1) {
12280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      AudioCodec codec(voe_codec.pltype, voe_codec.plname, voe_codec.plfreq,
12290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                       voe_codec.rate, voe_codec.channels, 0);
12300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      bool multi_rate = IsCodecMultiRate(voe_codec);
12310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Allow arbitrary rates for ISAC to be specified.
12320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (multi_rate) {
12330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // Set codec.bitrate to 0 so the check for codec.Matches() passes.
12340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        codec.bitrate = 0;
12350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
12360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (codec.Matches(in)) {
12370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (out) {
12380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          // Fixup the payload type.
12390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          voe_codec.pltype = in.id;
12400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          // Set bitrate if specified.
12420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          if (multi_rate && in.bitrate != 0) {
12430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            voe_codec.rate = in.bitrate;
12440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          }
12450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          // Apply codec-specific settings.
12470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          if (IsIsac(codec)) {
12480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            // If ISAC and an explicit bitrate is not specified,
12490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            // enable auto bandwidth adjustment.
12500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            voe_codec.rate = (in.bitrate > 0) ? in.bitrate : -1;
12510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          }
12520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          *out = voe_codec;
12530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
12540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        return true;
12550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
12560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
12570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
12580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return false;
12590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst std::vector<RtpHeaderExtension>&
12610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgWebRtcVoiceEngine::rtp_header_extensions() const {
12620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return rtp_header_extensions_;
12630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::SetLogging(int min_sev, const char* filter) {
12660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // if min_sev == -1, we keep the current log level.
12670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (min_sev >= 0) {
12680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SetTraceFilter(SeverityToFilter(min_sev));
12690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
12700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  log_options_ = filter;
12710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SetTraceOptions(initialized_ ? log_options_ : "");
12720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceEngine::GetLastEngineError() {
12750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return voe_wrapper_->error();
12760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::SetTraceFilter(int filter) {
12790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  log_filter_ = filter;
12800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  tracing_->SetTraceFilter(filter);
12810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// We suppport three different logging settings for VoiceEngine:
12840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 1. Observer callback that goes into talk diagnostic logfile.
12850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    Use --logfile and --loglevel
12860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
12870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 2. Encrypted VoiceEngine log for debugging VoiceEngine.
12880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    Use --voice_loglevel --voice_logfilter "tracefile file_name"
12890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
12900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 3. EC log and dump for debugging QualityEngine.
12910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    Use --voice_loglevel --voice_logfilter "recordEC file_name"
12920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
12930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// For more details see: "https://sites.google.com/a/google.com/wavelet/Home/
12940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//    Magic-Flute--RTC-Engine-/Magic-Flute-Command-Line-Parameters"
12950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::SetTraceOptions(const std::string& options) {
12960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Set encrypted trace file.
12970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<std::string> opts;
12982a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::tokenize(options, ' ', '"', '"', &opts);
12990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<std::string>::iterator tracefile =
13000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      std::find(opts.begin(), opts.end(), "tracefile");
13010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (tracefile != opts.end() && ++tracefile != opts.end()) {
13020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Write encrypted debug output (at same loglevel) to file
13030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // EncryptedTraceFile no longer supported.
13040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (tracing_->SetTraceFile(tracefile->c_str()) == -1) {
13050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR1(SetTraceFile, *tracefile);
13060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
13070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
13080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13095c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  // Allow trace options to override the trace filter. We default
13105c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  // it to log_filter_ (as a translation of libjingle log levels)
13115c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  // elsewhere, but this allows clients to explicitly set webrtc
13125c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  // log levels.
13135c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  std::vector<std::string>::iterator tracefilter =
13145c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org      std::find(opts.begin(), opts.end(), "tracefilter");
13155c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  if (tracefilter != opts.end() && ++tracefilter != opts.end()) {
13162a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    if (!tracing_->SetTraceFilter(rtc::FromString<int>(*tracefilter))) {
13175c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org      LOG_RTCERR1(SetTraceFilter, *tracefilter);
13185c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    }
13195c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  }
13205c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org
13210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Set AEC dump file
13220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<std::string>::iterator recordEC =
13230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      std::find(opts.begin(), opts.end(), "recordEC");
13240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (recordEC != opts.end()) {
13250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ++recordEC;
13260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (recordEC != opts.end())
13270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      StartAecDump(recordEC->c_str());
13280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    else
13290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      StopAecDump();
13300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
13310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
13320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Ignore spammy trace messages, mostly from the stats API when we haven't
13340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// gotten RTCP info yet from the remote side.
13350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::ShouldIgnoreTrace(const std::string& trace) {
13360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  static const char* kTracesToIgnore[] = {
13370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "\tfailed to GetReportBlockInformation",
13380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "GetRecCodec() failed to get received codec",
13390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "GetReceivedRtcpStatistics: Could not get received RTP statistics",
13400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "GetRemoteRTCPData() failed to measure statistics due to lack of received RTP and/or RTCP packets",  // NOLINT
13410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "GetRemoteRTCPData() failed to retrieve sender info for remote side",
13420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "GetRTPStatistics() failed to measure RTT since no RTP packets have been received yet",  // NOLINT
13430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "GetRTPStatistics() failed to read RTP statistics from the RTP/RTCP module",
13440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "GetRTPStatistics() failed to retrieve RTT from the RTP/RTCP module",
13450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "SenderInfoReceived No received SR",
13460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "StatisticsRTP() no statistics available",
13470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "TransmitMixer::TypingDetection() VE_TYPING_NOISE_WARNING message has been posted",  // NOLINT
13480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "TransmitMixer::TypingDetection() pending noise-saturation warning exists",  // NOLINT
13490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "GetRecPayloadType() failed to retrieve RX payload type (error=10026)", // NOLINT
13500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "StopPlayingFileAsMicrophone() isnot playing (error=8088)",
13510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    NULL
13520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  };
13530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (const char* const* p = kTracesToIgnore; *p; ++p) {
13540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (trace.find(*p) != std::string::npos) {
13550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return true;
13560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
13570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
13580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return false;
13590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
13600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
13620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              int length) {
13632a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::LoggingSeverity sev = rtc::LS_VERBOSE;
13640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (level == webrtc::kTraceError || level == webrtc::kTraceCritical)
13652a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    sev = rtc::LS_ERROR;
13660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  else if (level == webrtc::kTraceWarning)
13672a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    sev = rtc::LS_WARNING;
13680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo)
13692a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    sev = rtc::LS_INFO;
13700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  else if (level == webrtc::kTraceTerseInfo)
13712a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    sev = rtc::LS_INFO;
13720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Skip past boilerplate prefix text
13740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (length < 72) {
13750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    std::string msg(trace, length);
13760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "Malformed webrtc log message: ";
13770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_V(sev) << msg;
13780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
13790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    std::string msg(trace + 71, length - 72);
13800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ShouldIgnoreTrace(msg)) {
13810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_V(sev) << "webrtc: " << msg;
13820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
13830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
13840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
13850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::CallbackOnError(int channel_num, int err_code) {
13872a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope lock(&channels_cs_);
13880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  WebRtcVoiceMediaChannel* channel = NULL;
13890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 ssrc = 0;
13900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_WARNING) << "VoiceEngine error " << err_code << " reported on channel "
13910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << channel_num << ".";
13920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (FindChannelAndSsrc(channel_num, &channel, &ssrc)) {
13930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(channel != NULL);
13940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    channel->OnError(ssrc, err_code);
13950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
13960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "VoiceEngine channel " << channel_num
13970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << " could not be found in channel list when error reported.";
13980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
13990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::FindChannelAndSsrc(
14020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int channel_num, WebRtcVoiceMediaChannel** channel, uint32* ssrc) const {
14030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel != NULL && ssrc != NULL);
14040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *channel = NULL;
14060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *ssrc = 0;
14070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Find corresponding channel and ssrc
14080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ChannelList::const_iterator it = channels_.begin();
14090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      it != channels_.end(); ++it) {
14100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(*it != NULL);
14110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if ((*it)->FindSsrc(channel_num, ssrc)) {
14120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *channel = *it;
14130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return true;
14140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
14150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
14160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return false;
14180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// This method will search through the WebRtcVoiceMediaChannels and
14210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// obtain the voice engine's channel number.
14220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::FindChannelNumFromSsrc(
14230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 ssrc, MediaProcessorDirection direction, int* channel_num) {
14240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel_num != NULL);
14250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(direction == MPD_RX || direction == MPD_TX);
14260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *channel_num = -1;
14280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Find corresponding channel for ssrc.
14290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ChannelList::const_iterator it = channels_.begin();
14300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      it != channels_.end(); ++it) {
14310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(*it != NULL);
14320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (direction & MPD_RX) {
14330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *channel_num = (*it)->GetReceiveChannelNum(ssrc);
14340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
14350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (*channel_num == -1 && (direction & MPD_TX)) {
14360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *channel_num = (*it)->GetSendChannelNum(ssrc);
14370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
14380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (*channel_num != -1) {
14390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return true;
14400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
14410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
14420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_WARNING) << "FindChannelFromSsrc. No Channel Found for Ssrc: " << ssrc;
14430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return false;
14440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel *channel) {
14472a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope lock(&channels_cs_);
14480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channels_.push_back(channel);
14490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel *channel) {
14522a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope lock(&channels_cs_);
14530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ChannelList::iterator i = std::find(channels_.begin(),
14540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      channels_.end(),
14550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      channel);
14560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (i != channels_.end()) {
14570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    channels_.erase(i);
14580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
14590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::RegisterSoundclip(WebRtcSoundclipMedia *soundclip) {
14620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  soundclips_.push_back(soundclip);
14630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::UnregisterSoundclip(WebRtcSoundclipMedia *soundclip) {
14660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SoundclipList::iterator i = std::find(soundclips_.begin(),
14670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                        soundclips_.end(),
14680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                        soundclip);
14690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (i != soundclips_.end()) {
14700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    soundclips_.erase(i);
14710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
14720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Adjusts the default AGC target level by the specified delta.
14750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// NB: If we start messing with other config fields, we'll want
14760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// to save the current webrtc::AgcConfig as well.
14770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::AdjustAgcLevel(int delta) {
14780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  webrtc::AgcConfig config = default_agc_config_;
14790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  config.targetLeveldBOv -= delta;
14800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "Adjusting AGC level from default -"
14820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << default_agc_config_.targetLeveldBOv << "dB to -"
14830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << config.targetLeveldBOv << "dB";
14840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (voe_wrapper_->processing()->SetAgcConfig(config) == -1) {
14860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_RTCERR1(SetAgcConfig, config.targetLeveldBOv);
14870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
14880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
14890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
14900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::SetAudioDeviceModule(webrtc::AudioDeviceModule* adm,
14930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    webrtc::AudioDeviceModule* adm_sc) {
14940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (initialized_) {
14950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "SetAudioDeviceModule can not be called after Init.";
14960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
14970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
14980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (adm_) {
14990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    adm_->Release();
15000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    adm_ = NULL;
15010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (adm) {
15030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    adm_ = adm;
15040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    adm_->AddRef();
15050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (adm_sc_) {
15080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    adm_sc_->Release();
15090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    adm_sc_ = NULL;
15100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (adm_sc) {
15120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    adm_sc_ = adm_sc;
15130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    adm_sc_->AddRef();
15140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
15160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
15170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15182a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgbool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file) {
15192a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  FILE* aec_dump_file_stream = rtc::FdopenPlatformFileForWriting(file);
15201b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org  if (!aec_dump_file_stream) {
15211b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org    LOG(LS_ERROR) << "Could not open AEC dump file stream.";
15222a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    if (!rtc::ClosePlatformFile(file))
15231b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org      LOG(LS_WARNING) << "Could not close file.";
15241b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org    return false;
15251b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org  }
1526f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org  StopAecDump();
15271b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org  if (voe_wrapper_->processing()->StartDebugRecording(aec_dump_file_stream) !=
1528f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org      webrtc::AudioProcessing::kNoError) {
15291b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org    LOG_RTCERR0(StartDebugRecording);
15301b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org    fclose(aec_dump_file_stream);
1531f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org    return false;
1532f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org  }
1533f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org  is_dumping_aec_ = true;
1534f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org  return true;
1535f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org}
1536f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org
15370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::RegisterProcessor(
15380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 ssrc,
15390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    VoiceProcessor* voice_processor,
15400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    MediaProcessorDirection direction) {
15410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool register_with_webrtc = false;
15420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int channel_id = -1;
15430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool success = false;
15440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32* processor_ssrc = NULL;
15450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool found_channel = FindChannelNumFromSsrc(ssrc, direction, &channel_id);
15460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (voice_processor == NULL || !found_channel) {
15470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Media Processing Registration Failed. ssrc: " << ssrc
15480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        << " foundChannel: " << found_channel;
15490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
15500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  webrtc::ProcessingTypes processing_type;
15530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  {
15542a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::CritScope cs(&signal_media_critical_);
15550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (direction == MPD_RX) {
15560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      processing_type = webrtc::kPlaybackAllChannelsMixed;
15570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (SignalRxMediaFrame.is_empty()) {
15580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        register_with_webrtc = true;
15590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        processor_ssrc = &rx_processor_ssrc_;
15600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
15610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SignalRxMediaFrame.connect(voice_processor,
15620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                 &VoiceProcessor::OnFrame);
15630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
15640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      processing_type = webrtc::kRecordingPerChannel;
15650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (SignalTxMediaFrame.is_empty()) {
15660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        register_with_webrtc = true;
15670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        processor_ssrc = &tx_processor_ssrc_;
15680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
15690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SignalTxMediaFrame.connect(voice_processor,
15700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                 &VoiceProcessor::OnFrame);
15710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
15720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (register_with_webrtc) {
15740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // TODO(janahan): when registering consider instantiating a
15750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // a VoeMediaProcess object and not make the engine extend the interface.
15760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (voe()->media() && voe()->media()->
15770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        RegisterExternalMediaProcessing(channel_id,
15780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                        processing_type,
15790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                        *this) != -1) {
15800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_INFO) << "Media Processing Registration Succeeded. channel:"
15810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << channel_id;
15820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *processor_ssrc = ssrc;
15830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      success = true;
15840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
15850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR2(RegisterExternalMediaProcessing,
15860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  channel_id,
15870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  processing_type);
15880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      success = false;
15890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
15900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
15910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // If we don't have to register with the engine, we just needed to
15920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // connect a new processor, set success to true;
15930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    success = true;
15940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return success;
15960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
15970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::UnregisterProcessorChannel(
15990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    MediaProcessorDirection channel_direction,
16000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 ssrc,
16010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    VoiceProcessor* voice_processor,
16020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    MediaProcessorDirection processor_direction) {
16030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool success = true;
16040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  FrameSignal* signal;
16050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  webrtc::ProcessingTypes processing_type;
16060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32* processor_ssrc = NULL;
16070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (channel_direction == MPD_RX) {
16080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    signal = &SignalRxMediaFrame;
16090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    processing_type = webrtc::kPlaybackAllChannelsMixed;
16100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    processor_ssrc = &rx_processor_ssrc_;
16110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
16120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    signal = &SignalTxMediaFrame;
16130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    processing_type = webrtc::kRecordingPerChannel;
16140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    processor_ssrc = &tx_processor_ssrc_;
16150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
16160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
16170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int deregister_id = -1;
16180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  {
16192a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::CritScope cs(&signal_media_critical_);
16200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if ((processor_direction & channel_direction) != 0 && !signal->is_empty()) {
16210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      signal->disconnect(voice_processor);
16220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      int channel_id = -1;
16230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      bool found_channel = FindChannelNumFromSsrc(ssrc,
16240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                  channel_direction,
16250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                  &channel_id);
16260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (signal->is_empty() && found_channel) {
16270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        deregister_id = channel_id;
16280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
16290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
16300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
16310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (deregister_id != -1) {
16320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (voe()->media() &&
16330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        voe()->media()->DeRegisterExternalMediaProcessing(deregister_id,
16340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        processing_type) != -1) {
16350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *processor_ssrc = 0;
16360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_INFO) << "Media Processing DeRegistration Succeeded. channel:"
16370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << deregister_id;
16380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
16390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR2(DeRegisterExternalMediaProcessing,
16400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  deregister_id,
16410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  processing_type);
16420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      success = false;
16430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
16440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
16450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return success;
16460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
16470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
16480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::UnregisterProcessor(
16490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 ssrc,
16500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    VoiceProcessor* voice_processor,
16510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    MediaProcessorDirection direction) {
16520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool success = true;
16530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (voice_processor == NULL) {
16540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Media Processing Deregistration Failed. ssrc: "
16550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << ssrc;
16560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
16570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
16580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!UnregisterProcessorChannel(MPD_RX, ssrc, voice_processor, direction)) {
16590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    success = false;
16600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
16610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!UnregisterProcessorChannel(MPD_TX, ssrc, voice_processor, direction)) {
16620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    success = false;
16630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
16640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return success;
16650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
16660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
16670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Implementing method from WebRtc VoEMediaProcess interface
16680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Do not lock mux_channel_cs_ in this callback.
16690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::Process(int channel,
16700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                webrtc::ProcessingTypes type,
16710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                int16_t audio10ms[],
16720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                int length,
16730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                int sampling_freq,
16740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                bool is_stereo) {
16752a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::CritScope cs(&signal_media_critical_);
16760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    AudioFrame frame(audio10ms, length, sampling_freq, is_stereo);
16770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (type == webrtc::kPlaybackAllChannelsMixed) {
16780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SignalRxMediaFrame(rx_processor_ssrc_, MPD_RX, &frame);
16790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (type == webrtc::kRecordingPerChannel) {
16800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SignalTxMediaFrame(tx_processor_ssrc_, MPD_TX, &frame);
16810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
16820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_WARNING) << "Media Processing invoked unexpectedly."
16830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      << " channel: " << channel << " type: " << type
16840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      << " tx_ssrc: " << tx_processor_ssrc_
16850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      << " rx_ssrc: " << rx_processor_ssrc_;
16860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
16870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
16880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
16890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
16900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!is_dumping_aec_) {
16910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Start dumping AEC when we are not dumping.
16920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (voe_wrapper_->processing()->StartDebugRecording(
16930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        filename.c_str()) != webrtc::AudioProcessing::kNoError) {
1694f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org      LOG_RTCERR1(StartDebugRecording, filename.c_str());
16950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
16960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      is_dumping_aec_ = true;
16970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
16980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
16990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
17000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
17010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::StopAecDump() {
17020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (is_dumping_aec_) {
17030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Stop dumping AEC when we are dumping.
17040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (voe_wrapper_->processing()->StopDebugRecording() !=
17050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        webrtc::AudioProcessing::kNoError) {
17060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR0(StopDebugRecording);
17070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
17080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    is_dumping_aec_ = false;
17090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
17100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
17110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
171297fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.orgint WebRtcVoiceEngine::CreateVoiceChannel(VoEWrapper* voice_engine_wrapper) {
171397fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org  return voice_engine_wrapper->base()->CreateChannel(voe_config_);
171497fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org}
171597fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org
171697fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.orgint WebRtcVoiceEngine::CreateMediaVoiceChannel() {
171797fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org  return CreateVoiceChannel(voe_wrapper_.get());
171897fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org}
171997fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org
172097fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.orgint WebRtcVoiceEngine::CreateSoundclipVoiceChannel() {
172197fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org  return CreateVoiceChannel(voe_wrapper_sc_.get());
172297fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org}
172397fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org
1724b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.orgclass WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer
1725b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    : public AudioRenderer::Sink {
1726b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org public:
1727b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  WebRtcVoiceChannelRenderer(int ch,
1728b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org                             webrtc::AudioTransport* voe_audio_transport)
1729b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      : channel_(ch),
1730b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org        voe_audio_transport_(voe_audio_transport),
1731b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org        renderer_(NULL) {
1732b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  }
1733b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  virtual ~WebRtcVoiceChannelRenderer() {
1734b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    Stop();
1735b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  }
1736b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org
1737b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // Starts the rendering by setting a sink to the renderer to get data
1738b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // callback.
1739e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  // This method is called on the libjingle worker thread.
1740b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // TODO(xians): Make sure Start() is called only once.
1741b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  void Start(AudioRenderer* renderer) {
17422a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::CritScope lock(&lock_);
1743b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    ASSERT(renderer != NULL);
1744e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    if (renderer_ != NULL) {
1745b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      ASSERT(renderer_ == renderer);
1746b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      return;
1747b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    }
1748b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org
1749b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    // TODO(xians): Remove AddChannel() call after Chrome turns on APM
1750b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    // in getUserMedia by default.
1751b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    renderer->AddChannel(channel_);
1752b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    renderer->SetSink(this);
1753b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    renderer_ = renderer;
1754b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  }
1755b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org
1756b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // Stops rendering by setting the sink of the renderer to NULL. No data
1757b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // callback will be received after this method.
1758e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  // This method is called on the libjingle worker thread.
1759b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  void Stop() {
17602a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::CritScope lock(&lock_);
1761e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    if (renderer_ == NULL)
1762b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      return;
1763b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org
1764b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    renderer_->RemoveChannel(channel_);
1765b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    renderer_->SetSink(NULL);
1766b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    renderer_ = NULL;
1767b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  }
1768b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org
1769b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // AudioRenderer::Sink implementation.
1770e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  // This method is called on the audio thread.
1771b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  virtual void OnData(const void* audio_data,
1772b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org                      int bits_per_sample,
1773b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org                      int sample_rate,
1774b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org                      int number_of_channels,
1775b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org                      int number_of_frames) OVERRIDE {
1776e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    voe_audio_transport_->OnData(channel_,
1777e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org                                 audio_data,
1778e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org                                 bits_per_sample,
1779e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org                                 sample_rate,
1780e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org                                 number_of_channels,
1781e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org                                 number_of_frames);
1782e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  }
1783e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org
1784e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  // Callback from the |renderer_| when it is going away. In case Start() has
1785e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  // never been called, this callback won't be triggered.
1786e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  virtual void OnClose() OVERRIDE {
17872a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::CritScope lock(&lock_);
1788e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    // Set |renderer_| to NULL to make sure no more callback will get into
1789e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    // the renderer.
1790e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    renderer_ = NULL;
1791b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  }
1792b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org
1793b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // Accessor to the VoE channel ID.
1794b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  int channel() const { return channel_; }
1795b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org
1796b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org private:
1797b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  const int channel_;
1798b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  webrtc::AudioTransport* const voe_audio_transport_;
1799b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org
1800b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler.
1801b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // PeerConnection will make sure invalidating the pointer before the object
1802b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // goes away.
1803b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  AudioRenderer* renderer_;
1804e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org
1805e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  // Protects |renderer_| in Start(), Stop() and OnClose().
18062a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CriticalSection lock_;
18077162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org};
18087162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
18090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// WebRtcVoiceMediaChannel
18100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgWebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine *engine)
18110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : WebRtcMediaChannel<VoiceMediaChannel, WebRtcVoiceEngine>(
18120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          engine,
181397fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org          engine->CreateMediaVoiceChannel()),
1814cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org      send_bw_setting_(false),
1815cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org      send_bw_bps_(0),
18160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options_(),
18170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      dtmf_allowed_(false),
18180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      desired_playout_(false),
18190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      nack_enabled_(false),
18200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      playout_(false),
18214ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org      typing_noise_detected_(false),
18220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      desired_send_(SEND_NOTHING),
18230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      send_(SEND_NOTHING),
18245462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org      shared_bwe_vie_(NULL),
18255462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org      shared_bwe_vie_channel_(-1),
18260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      default_receive_ssrc_(0) {
18270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  engine->RegisterChannel(this);
18280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel "
18290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << voe_channel();
18300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1831f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  ConfigureSendChannel(voe_channel());
18320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
18330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
18340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgWebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
18350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel "
18360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << voe_channel();
1837d7afd1f0d8473565079f8f17de76607691161dc9buildbot@webrtc.org  SetupSharedBandwidthEstimation(NULL, -1);
18380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1839f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // Remove any remaining send streams, the default channel will be deleted
1840f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // later.
1841f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  while (!send_channels_.empty())
1842f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    RemoveSendStream(send_channels_.begin()->first);
18430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
18440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Unregister ourselves from the engine.
18450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  engine()->UnregisterChannel(this);
18460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Remove any remaining streams.
18477162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  while (!receive_channels_.empty()) {
18487162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    RemoveRecvStream(receive_channels_.begin()->first);
18490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
18500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1851f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // Delete the default channel.
1852f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  DeleteChannel(voe_channel());
18530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
18540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
18550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
18560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "Setting voice channel options: "
18570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << options.ToString();
18580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
185980303b162fe139828d0661df23e03f09126508acwu@webrtc.org  // Check if DSCP value is changed from previous.
186080303b162fe139828d0661df23e03f09126508acwu@webrtc.org  bool dscp_option_changed = (options_.dscp != options.dscp);
186180303b162fe139828d0661df23e03f09126508acwu@webrtc.org
1862f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // TODO(xians): Add support to set different options for different send
1863f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // streams after we support multiple APMs.
1864f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
18650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We retain all of the existing options, and apply the given ones
18660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // on top.  This means there is no way to "clear" options such that
18670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // they go back to the engine default.
18680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  options_.SetAll(options);
18690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
18700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (send_ != SEND_NOTHING) {
18710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!engine()->SetOptionOverrides(options_)) {
18720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_WARNING) <<
18730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          "Failed to engine SetOptionOverrides during channel SetOptions.";
18740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
18750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
18760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
18770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Will be interpreted when appropriate.
18780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
18790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
18805c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  // Receiver-side auto gain control happens per channel, so set it here from
18815c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  // options. Note that, like conference mode, setting it on the engine won't
18825c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  // have the desired effect, since voice channels don't inherit options from
18835c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  // the media engine when those options are applied per-channel.
18845c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  bool rx_auto_gain_control;
18855c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  if (options.rx_auto_gain_control.Get(&rx_auto_gain_control)) {
18865c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    if (engine()->voe()->processing()->SetRxAgcStatus(
18875c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org            voe_channel(), rx_auto_gain_control,
18885c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org            webrtc::kAgcFixedDigital) == -1) {
18895c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org      LOG_RTCERR1(SetRxAgcStatus, rx_auto_gain_control);
18905c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org      return false;
18915c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    } else {
18925c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org      LOG(LS_VERBOSE) << "Rx auto gain set to " << rx_auto_gain_control
18935c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org                      << " with mode " << webrtc::kAgcFixedDigital;
18945c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    }
18955c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  }
18965c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  if (options.rx_agc_target_dbov.IsSet() ||
18975c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org      options.rx_agc_digital_compression_gain.IsSet() ||
18985c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org      options.rx_agc_limiter.IsSet()) {
18995c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    webrtc::AgcConfig config;
19005c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    // If only some of the options are being overridden, get the current
19015c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    // settings for the channel and bail if they aren't available.
19025c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    if (!options.rx_agc_target_dbov.IsSet() ||
19035c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org        !options.rx_agc_digital_compression_gain.IsSet() ||
19045c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org        !options.rx_agc_limiter.IsSet()) {
19055c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org      if (engine()->voe()->processing()->GetRxAgcConfig(
19065c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org              voe_channel(), config) != 0) {
19075c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org        LOG(LS_ERROR) << "Failed to get default rx agc configuration for "
19085c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org                      << "channel " << voe_channel() << ". Since not all rx "
19095c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org                      << "agc options are specified, unable to safely set rx "
19105c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org                      << "agc options.";
19115c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org        return false;
19125c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org      }
19135c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    }
19145c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    config.targetLeveldBOv =
19155c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org        options.rx_agc_target_dbov.GetWithDefaultIfUnset(
19165c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org            config.targetLeveldBOv);
19175c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    config.digitalCompressionGaindB =
19185c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org        options.rx_agc_digital_compression_gain.GetWithDefaultIfUnset(
19195c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org            config.digitalCompressionGaindB);
19205c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    config.limiterEnable = options.rx_agc_limiter.GetWithDefaultIfUnset(
19215c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org        config.limiterEnable);
19225c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    if (engine()->voe()->processing()->SetRxAgcConfig(
19235c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org            voe_channel(), config) == -1) {
19245c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org      LOG_RTCERR4(SetRxAgcConfig, voe_channel(), config.targetLeveldBOv,
19255c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org                  config.digitalCompressionGaindB, config.limiterEnable);
19265c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org      return false;
19275c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org    }
19285c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org  }
192980303b162fe139828d0661df23e03f09126508acwu@webrtc.org  if (dscp_option_changed) {
19302a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT;
19318485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org    if (options_.dscp.GetWithDefaultIfUnset(false))
193280303b162fe139828d0661df23e03f09126508acwu@webrtc.org      dscp = kAudioDscpValue;
193380303b162fe139828d0661df23e03f09126508acwu@webrtc.org    if (MediaChannel::SetDscp(dscp) != 0) {
193480303b162fe139828d0661df23e03f09126508acwu@webrtc.org      LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel";
193580303b162fe139828d0661df23e03f09126508acwu@webrtc.org    }
193680303b162fe139828d0661df23e03f09126508acwu@webrtc.org  }
19375c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org
19385462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  // Force update of Video Engine BWE forwarding to reflect experiment setting.
19395462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  if (!SetupSharedBandwidthEstimation(shared_bwe_vie_,
19405462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org                                      shared_bwe_vie_channel_)) {
19415462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    return false;
19425462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  }
19435462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org
19440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "Set voice channel options.  Current options: "
19450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << options_.ToString();
19460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
19470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
19480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
19490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetRecvCodecs(
19500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::vector<AudioCodec>& codecs) {
19510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Set the payload types to be used for incoming media.
19520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "Setting receive voice codecs:";
19530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
19540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<AudioCodec> new_codecs;
19550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Find all new codecs. We allow adding new codecs but don't allow changing
19560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // the payload type of codecs that is already configured since we might
19570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // already be receiving packets with that payload type.
19580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<AudioCodec>::const_iterator it = codecs.begin();
19597162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org       it != codecs.end(); ++it) {
19600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    AudioCodec old_codec;
19610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (FindCodec(recv_codecs_, *it, &old_codec)) {
19620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (old_codec.id != it->id) {
19630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG(LS_ERROR) << it->name << " payload type changed.";
19640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        return false;
19650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
19660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
19670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      new_codecs.push_back(*it);
19680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
19690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
19700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (new_codecs.empty()) {
19710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // There are no new codecs to configure. Already configured codecs are
19720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // never removed.
19730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
19740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
19750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
19760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (playout_) {
19770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Receive codecs can not be changed while playing. So we temporarily
19780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // pause playout.
19790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    PausePlayout();
19800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
19810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
19827162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  bool ret = true;
19830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<AudioCodec>::const_iterator it = new_codecs.begin();
19840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != new_codecs.end() && ret; ++it) {
19850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    webrtc::CodecInst voe_codec;
19860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (engine()->FindWebRtcCodec(*it, &voe_codec)) {
19870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_INFO) << ToString(*it);
19880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      voe_codec.pltype = it->id;
19897162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      if (default_receive_ssrc_ == 0) {
19907162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org        // Set the receive codecs on the default channel explicitly if the
19917162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org        // default channel is not used by |receive_channels_|, this happens in
19927162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org        // conference mode or in non-conference mode when there is no playout
19937162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org        // channel.
19947162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org        // TODO(xians): Figure out how we use the default channel in conference
19957162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org        // mode.
19967162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org        if (engine()->voe()->codec()->SetRecPayloadType(
19977162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org            voe_channel(), voe_codec) == -1) {
19987162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org          LOG_RTCERR2(SetRecPayloadType, voe_channel(), ToString(voe_codec));
19997162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org          ret = false;
20007162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org        }
20010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
20020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
20030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Set the receive codecs on all receiving channels.
20047162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      for (ChannelMap::iterator it = receive_channels_.begin();
20057162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org           it != receive_channels_.end() && ret; ++it) {
20060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (engine()->voe()->codec()->SetRecPayloadType(
2007b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org                it->second->channel(), voe_codec) == -1) {
2008b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org          LOG_RTCERR2(SetRecPayloadType, it->second->channel(),
20097162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org                      ToString(voe_codec));
20100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          ret = false;
20110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
20120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
20130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
20140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_WARNING) << "Unknown codec " << ToString(*it);
20150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ret = false;
20160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
20170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
20180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (ret) {
20190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    recv_codecs_ = codecs;
20200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
20210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
20220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (desired_playout_ && !playout_) {
20230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ResumePlayout();
20240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
20250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ret;
20260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
20270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
20280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetSendCodecs(
2029952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org    int channel, const std::vector<AudioCodec>& codecs) {
203007617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org  // Disable VAD, FEC, and RED unless we know the other side wants them.
2031952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  engine()->voe()->codec()->SetVADStatus(channel, false);
2032952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
203307617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#ifdef USE_WEBRTC_DEV_BRANCH
203407617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org  engine()->voe()->rtp()->SetREDStatus(channel, false);
203507617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org  engine()->voe()->codec()->SetFECStatus(channel, false);
203607617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#else
203707617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org  // TODO(minyue): Remove code under #else case after new WebRTC roll.
2038952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  engine()->voe()->rtp()->SetFECStatus(channel, false);
203907617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#endif  // USE_WEBRTC_DEV_BRANCH
20400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
20410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Scan through the list to figure out the codec to use for sending, along
20420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // with the proper configuration for VAD and DTMF.
20437587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  bool found_send_codec = false;
20440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  webrtc::CodecInst send_codec;
20450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  memset(&send_codec, 0, sizeof(send_codec));
20460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2047a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org  bool nack_enabled = nack_enabled_;
2048c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org  bool enable_codec_fec = false;
2049a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org
2050ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  // max_playback_rate <= 0 will not trigger setting of maximum encoding
2051ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  // bandwidth.
2052ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  int max_playback_rate = 0;
2053ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org
20547587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  // Set send codec (the first non-telephone-event/CN codec)
20550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<AudioCodec>::const_iterator it = codecs.begin();
20560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != codecs.end(); ++it) {
20570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Ignore codecs we don't know about. The negotiation step should prevent
20580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // this, but double-check to be sure.
20590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    webrtc::CodecInst voe_codec;
20600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!engine()->FindWebRtcCodec(*it, &voe_codec)) {
20618485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org      LOG(LS_WARNING) << "Unknown codec " << ToString(*it);
20620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      continue;
20630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
20640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
20657587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    if (IsTelephoneEventCodec(it->name) || IsCNCodec(it->name)) {
20667587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      // Skip telephone-event/CN codec, which will be handled later.
20677587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      continue;
20687587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    }
20697587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org
20700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
20717587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    // We'll use the first codec in the list to actually send audio data.
20727587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    // Be sure to use the payload type requested by the remote side.
207307617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org    // "red", for RED audio, is a special case where the actual codec to be
20747587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    // used is specified in params.
20757587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    if (IsRedCodec(it->name)) {
20767587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      // Parse out the RED parameters. If we fail, just ignore RED;
20777587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      // we don't support all possible params/usage scenarios.
20787587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      if (!GetRedSendCodec(*it, codecs, &send_codec)) {
20797587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org        continue;
20807587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      }
20817587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org
20827587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      // Enable redundant encoding of the specified codec. Treat any
20837587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      // failure as a fatal internal error.
208407617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#ifdef USE_WEBRTC_DEV_BRANCH
208507617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org      LOG(LS_INFO) << "Enabling RED on channel " << channel;
208607617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org      if (engine()->voe()->rtp()->SetREDStatus(channel, true, it->id) == -1) {
208707617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org        LOG_RTCERR3(SetREDStatus, channel, true, it->id);
208807617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#else
208907617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org      // TODO(minyue): Remove code under #else case after new WebRTC roll.
20907587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      LOG(LS_INFO) << "Enabling FEC";
20917587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      if (engine()->voe()->rtp()->SetFECStatus(channel, true, it->id) == -1) {
20927587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org        LOG_RTCERR3(SetFECStatus, channel, true, it->id);
209307617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#endif  // USE_WEBRTC_DEV_BRANCH
20947587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org        return false;
20957587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      }
20967587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    } else {
20977587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      send_codec = voe_codec;
2098a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org      nack_enabled = IsNackEnabled(*it);
2099ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org      // For Opus as the send codec, we are to enable inband FEC if requested
2100ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org      // and set maximum playback rate.
2101ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org      if (IsOpus(*it)) {
2102ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org        GetOpusConfig(*it, &send_codec, &enable_codec_fec, &max_playback_rate);
2103ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org      }
21047587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    }
21057587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    found_send_codec = true;
21067587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    break;
21077587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  }
21087587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org
2109a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org  if (nack_enabled_ != nack_enabled) {
2110a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org    SetNack(channel, nack_enabled);
2111a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org    nack_enabled_ = nack_enabled;
2112a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org  }
2113a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org
21147587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  if (!found_send_codec) {
21157587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    LOG(LS_WARNING) << "Received empty list of codecs.";
21167587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    return false;
21177587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  }
21187587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org
21197587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  // Set the codec immediately, since SetVADStatus() depends on whether
21207587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  // the current codec is mono or stereo.
21217587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  if (!SetSendCodec(channel, send_codec))
21227587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    return false;
21237587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org
2124c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org  // FEC should be enabled after SetSendCodec.
2125c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org  if (enable_codec_fec) {
2126c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org    LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel "
2127c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org                 << channel;
2128c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org#ifdef USE_WEBRTC_DEV_BRANCH
2129c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org    if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) {
2130c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org      // Enable codec internal FEC. Treat any failure as fatal internal error.
2131c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org      LOG_RTCERR2(SetFECStatus, channel, true);
2132c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org      return false;
2133c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org    }
2134c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org#endif  // USE_WEBRTC_DEV_BRANCH
2135c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org  }
2136c547a07407ddf9d3bb52be8874eec40f47889413buildbot@webrtc.org
2137ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  // maxplaybackrate should be set after SetSendCodec.
2138ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  if (max_playback_rate > 0) {
2139ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org    LOG(LS_INFO) << "Attempt to set maximum playback rate to "
2140ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org                 << max_playback_rate
2141ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org                 << " Hz on channel "
2142ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org                 << channel;
2143ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org#ifdef USE_WEBRTC_DEV_BRANCH
2144ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org    // (max_playback_rate + 1) >> 1 is to obtain ceil(max_playback_rate / 2.0).
2145ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org    if (engine()->voe()->codec()->SetOpusMaxPlaybackRate(
2146ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org        channel, max_playback_rate) == -1) {
2147ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org      LOG(LS_WARNING) << "Could not set maximum playback rate.";
2148ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org    }
2149ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org#endif
2150ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org  }
2151ded08bf766f814b46b099c7949f9c9e1726a6adebuildbot@webrtc.org
21527587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  // Always update the |send_codec_| to the currently set send codec.
21537587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  send_codec_.reset(new webrtc::CodecInst(send_codec));
21547587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org
21557587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  if (send_bw_setting_) {
21567587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    SetSendBandwidthInternal(send_bw_bps_);
21577587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  }
21587587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org
21597587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  // Loop through the codecs list again to config the telephone-event/CN codec.
21607587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org  for (std::vector<AudioCodec>::const_iterator it = codecs.begin();
21617587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org       it != codecs.end(); ++it) {
21627587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    // Ignore codecs we don't know about. The negotiation step should prevent
21637587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    // this, but double-check to be sure.
21647587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    webrtc::CodecInst voe_codec;
21657587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    if (!engine()->FindWebRtcCodec(*it, &voe_codec)) {
21667587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      LOG(LS_WARNING) << "Unknown codec " << ToString(*it);
21677587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      continue;
21687587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    }
21697587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org
2170f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // Find the DTMF telephone event "codec" and tell VoiceEngine channels
2171f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // about it.
21727587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    if (IsTelephoneEventCodec(it->name)) {
2173952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      if (engine()->voe()->dtmf()->SetSendTelephoneEventPayloadType(
2174952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org              channel, it->id) == -1) {
2175952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org        LOG_RTCERR2(SetSendTelephoneEventPayloadType, channel, it->id);
2176952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org        return false;
21770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
21787587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org    } else if (IsCNCodec(it->name)) {
21797587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      // Turn voice activity detection/comfort noise on if supported.
21807587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      // Set the wideband CN payload type appropriately.
21817587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org      // (narrowband always uses the static payload type 13).
21820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      webrtc::PayloadFrequencies cn_freq;
21830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      switch (it->clockrate) {
21840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        case 8000:
21850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          cn_freq = webrtc::kFreq8000Hz;
21860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          break;
21870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        case 16000:
21880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          cn_freq = webrtc::kFreq16000Hz;
21890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          break;
21900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        case 32000:
21910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          cn_freq = webrtc::kFreq32000Hz;
21920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          break;
21930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        default:
21940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          LOG(LS_WARNING) << "CN frequency " << it->clockrate
21950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          << " not supported.";
21960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          continue;
21970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2198952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      // Set the CN payloadtype and the VAD status.
2199952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      // The CN payload type for 8000 Hz clockrate is fixed at 13.
2200952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      if (cn_freq != webrtc::kFreq8000Hz) {
2201952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org        if (engine()->voe()->codec()->SetSendCNPayloadType(
2202952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org                channel, it->id, cn_freq) == -1) {
2203952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org          LOG_RTCERR3(SetSendCNPayloadType, channel, it->id, cn_freq);
2204952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org          // TODO(ajm): This failure condition will be removed from VoE.
2205952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org          // Restore the return here when we update to a new enough webrtc.
2206952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org          //
2207952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org          // Not returning false because the SetSendCNPayloadType will fail if
2208952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org          // the channel is already sending.
2209952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org          // This can happen if the remote description is applied twice, for
2210952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org          // example in the case of ROAP on top of JSEP, where both side will
2211952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org          // send the offer.
22120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
2213952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      }
2214952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      // Only turn on VAD if we have a CN payload type that matches the
2215952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      // clockrate for the codec we are going to use.
2216952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      if (it->clockrate == send_codec.plfreq) {
2217952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org        LOG(LS_INFO) << "Enabling VAD";
2218952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org        if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) {
2219952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org          LOG_RTCERR2(SetVADStatus, channel, true);
2220952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org          return false;
22210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
22220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
22230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2224cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org  }
2225952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  return true;
2226952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org}
2227952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org
2228952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.orgbool WebRtcVoiceMediaChannel::SetSendCodecs(
2229952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org    const std::vector<AudioCodec>& codecs) {
2230952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  dtmf_allowed_ = false;
2231952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  for (std::vector<AudioCodec>::const_iterator it = codecs.begin();
2232952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org       it != codecs.end(); ++it) {
2233952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org    // Find the DTMF telephone event "codec".
2234952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org    if (_stricmp(it->name.c_str(), "telephone-event") == 0 ||
2235952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org        _stricmp(it->name.c_str(), "audio/telephone-event") == 0) {
2236952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      dtmf_allowed_ = true;
2237952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org    }
2238952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  }
2239952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org
2240952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  // Cache the codecs in order to configure the channel created later.
2241952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  send_codecs_ = codecs;
2242952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  for (ChannelMap::iterator iter = send_channels_.begin();
2243952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org       iter != send_channels_.end(); ++iter) {
2244b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    if (!SetSendCodecs(iter->second->channel(), codecs)) {
22450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
2246952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org    }
22470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
22480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2249a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org  // Set nack status on receive channels and update |nack_enabled_|.
2250952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  SetNack(receive_channels_, nack_enabled_);
22510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
22520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2253f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2254f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.orgvoid WebRtcVoiceMediaChannel::SetNack(const ChannelMap& channels,
2255f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org                                      bool nack_enabled) {
2256f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  for (ChannelMap::const_iterator it = channels.begin();
2257f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org       it != channels.end(); ++it) {
2258b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    SetNack(it->second->channel(), nack_enabled);
2259f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
2260f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org}
2261f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2262952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.orgvoid WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) {
22630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (nack_enabled) {
2264952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org    LOG(LS_INFO) << "Enabling NACK for channel " << channel;
22650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets);
22660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
2267952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org    LOG(LS_INFO) << "Disabling NACK for channel " << channel;
22680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
22690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
22700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
22710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
22720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetSendCodec(
22730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const webrtc::CodecInst& send_codec) {
22740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "Selected voice codec " << ToString(send_codec)
22750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << ", bitrate=" << send_codec.rate;
2276f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  for (ChannelMap::iterator iter = send_channels_.begin();
2277f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org       iter != send_channels_.end(); ++iter) {
2278b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    if (!SetSendCodec(iter->second->channel(), send_codec))
2279f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      return false;
22800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2281f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2282f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  return true;
2283f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org}
2284f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2285f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.orgbool WebRtcVoiceMediaChannel::SetSendCodec(
2286f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    int channel, const webrtc::CodecInst& send_codec) {
2287f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  LOG(LS_INFO) << "Send channel " << channel <<  " selected voice codec "
2288f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org               << ToString(send_codec) << ", bitrate=" << send_codec.rate;
2289f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2290a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org  webrtc::CodecInst current_codec;
2291a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org  if (engine()->voe()->codec()->GetSendCodec(channel, current_codec) == 0 &&
2292a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org      (send_codec == current_codec)) {
2293a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org    // Codec is already configured, we can return without setting it again.
2294a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org    return true;
2295a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org  }
2296a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org
2297f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (engine()->voe()->codec()->SetSendCodec(channel, send_codec) == -1) {
2298f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    LOG_RTCERR2(SetSendCodec, channel, ToString(send_codec));
2299f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    return false;
2300f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
23010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
23020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
23030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
23040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetRecvRtpHeaderExtensions(
23050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
23062ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  if (receive_extensions_ == extensions) {
23072ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    return true;
23082ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  }
23092ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org
23102ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  // The default channel may or may not be in |receive_channels_|. Set the rtp
23112ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  // header extensions for default channel regardless.
23122ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  if (!SetChannelRecvRtpHeaderExtensions(voe_channel(), extensions)) {
23132ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    return false;
23142ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  }
23153ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org
23163ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  // Loop through all receive channels and enable/disable the extensions.
23173ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  for (ChannelMap::const_iterator channel_it = receive_channels_.begin();
23183ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org       channel_it != receive_channels_.end(); ++channel_it) {
23192ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    if (!SetChannelRecvRtpHeaderExtensions(channel_it->second->channel(),
23202ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org                                           extensions)) {
23213ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org      return false;
23223ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org    }
23233ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  }
23242ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org
23252ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  receive_extensions_ = extensions;
23260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
23270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
23280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
23292ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.orgbool WebRtcVoiceMediaChannel::SetChannelRecvRtpHeaderExtensions(
23302ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    int channel_id, const std::vector<RtpHeaderExtension>& extensions) {
23313ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  const RtpHeaderExtension* audio_level_extension =
23323ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org      FindHeaderExtension(extensions, kRtpAudioLevelHeaderExtension);
23333ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  if (!SetHeaderExtension(
23342ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org      &webrtc::VoERTP_RTCP::SetReceiveAudioLevelIndicationStatus, channel_id,
23353ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org      audio_level_extension)) {
23363ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org    return false;
23373ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  }
23382ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org
23392ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  const RtpHeaderExtension* send_time_extension =
23402ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org      FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
23413ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  if (!SetHeaderExtension(
23422ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org      &webrtc::VoERTP_RTCP::SetReceiveAbsoluteSenderTimeStatus, channel_id,
23433ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org      send_time_extension)) {
23443ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org    return false;
23453ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  }
23462ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  return true;
23472ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org}
23482ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org
23492ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.orgbool WebRtcVoiceMediaChannel::SetSendRtpHeaderExtensions(
23502ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
23512ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  if (send_extensions_ == extensions) {
23522ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    return true;
23532ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  }
23542ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org
23552ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  // The default channel may or may not be in |send_channels_|. Set the rtp
23562ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  // header extensions for default channel regardless.
23572ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org
23582ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  if (!SetChannelSendRtpHeaderExtensions(voe_channel(), extensions)) {
23592ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    return false;
23602ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  }
23610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
23622ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  // Loop through all send channels and enable/disable the extensions.
23633ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  for (ChannelMap::const_iterator channel_it = send_channels_.begin();
23643ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org       channel_it != send_channels_.end(); ++channel_it) {
23652ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    if (!SetChannelSendRtpHeaderExtensions(channel_it->second->channel(),
23662ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org                                           extensions)) {
23673ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org      return false;
23683ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org    }
23690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
23702ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org
23712ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  send_extensions_ = extensions;
23722ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  return true;
23732ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org}
23742ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org
23752ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.orgbool WebRtcVoiceMediaChannel::SetChannelSendRtpHeaderExtensions(
23762ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    int channel_id, const std::vector<RtpHeaderExtension>& extensions) {
23772ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  const RtpHeaderExtension* audio_level_extension =
23782ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org      FindHeaderExtension(extensions, kRtpAudioLevelHeaderExtension);
23792ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org
23802ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  if (!SetHeaderExtension(
23812ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org      &webrtc::VoERTP_RTCP::SetSendAudioLevelIndicationStatus, channel_id,
23822ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org      audio_level_extension)) {
23832ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    return false;
23842ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  }
23852ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org
23862ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  const RtpHeaderExtension* send_time_extension =
23872ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org      FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
23882ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  if (!SetHeaderExtension(
23892ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org      &webrtc::VoERTP_RTCP::SetSendAbsoluteSenderTimeStatus, channel_id,
23902ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org      send_time_extension)) {
23912ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    return false;
23922ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  }
23932ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org
23940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
23950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
23960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
23970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetPlayout(bool playout) {
23980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  desired_playout_ = playout;
23990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ChangePlayout(desired_playout_);
24000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
24010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
24020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::PausePlayout() {
24030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ChangePlayout(false);
24040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
24050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
24060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::ResumePlayout() {
24070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ChangePlayout(desired_playout_);
24080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
24090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
24100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::ChangePlayout(bool playout) {
24110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (playout_ == playout) {
24120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
24130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
24140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
24157162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  // Change the playout of all channels to the new state.
24160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool result = true;
24177162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  if (receive_channels_.empty()) {
24180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Only toggle the default channel if we don't have any other channels.
24190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    result = SetPlayout(voe_channel(), playout);
24200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
24217162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  for (ChannelMap::iterator it = receive_channels_.begin();
24227162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org       it != receive_channels_.end() && result; ++it) {
2423b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    if (!SetPlayout(it->second->channel(), playout)) {
24247162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      LOG(LS_ERROR) << "SetPlayout " << playout << " on channel "
2425b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org                    << it->second->channel() << " failed";
24260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      result = false;
24270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
24280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
24290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
24300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (result) {
24310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    playout_ = playout;
24320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
24330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return result;
24340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
24350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
24360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetSend(SendFlags send) {
24370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  desired_send_ = send;
2438f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (!send_channels_.empty())
24390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ChangeSend(desired_send_);
24400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
24410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
24420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
24430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::PauseSend() {
24440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ChangeSend(SEND_NOTHING);
24450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
24460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
24470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::ResumeSend() {
24480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ChangeSend(desired_send_);
24490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
24500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
24510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::ChangeSend(SendFlags send) {
24520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (send_ == send) {
24530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
24540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
24550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2456f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // Change the settings on each send channel.
2457f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (send == SEND_MICROPHONE)
24580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    engine()->SetOptionOverrides(options_);
24590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2460f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // Change the settings on each send channel.
2461f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  for (ChannelMap::iterator iter = send_channels_.begin();
2462f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org       iter != send_channels_.end(); ++iter) {
2463b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    if (!ChangeSend(iter->second->channel(), send))
24640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
2465f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
2466f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2467f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // Clear up the options after stopping sending.
2468f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (send == SEND_NOTHING)
2469f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    engine()->ClearOptionOverrides();
2470f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2471f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  send_ = send;
2472f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  return true;
2473f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org}
2474f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2475f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.orgbool WebRtcVoiceMediaChannel::ChangeSend(int channel, SendFlags send) {
2476f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (send == SEND_MICROPHONE) {
2477f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    if (engine()->voe()->base()->StartSend(channel) == -1) {
2478f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      LOG_RTCERR1(StartSend, channel);
24790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
24800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
24810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (engine()->voe()->file() &&
2482f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        engine()->voe()->file()->StopPlayingFileAsMicrophone(channel) == -1) {
2483f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      LOG_RTCERR1(StopPlayingFileAsMicrophone, channel);
24840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
24850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
24860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {  // SEND_NOTHING
2487f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    ASSERT(send == SEND_NOTHING);
2488f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    if (engine()->voe()->base()->StopSend(channel) == -1) {
2489f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      LOG_RTCERR1(StopSend, channel);
2490f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      return false;
24910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2492f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
24930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2494f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  return true;
2495f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org}
2496f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
24972ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org// TODO(ronghuawu): Change this method to return bool.
2498f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.orgvoid WebRtcVoiceMediaChannel::ConfigureSendChannel(int channel) {
2499f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (engine()->voe()->network()->RegisterExternalTransport(
2500f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          channel, *this) == -1) {
2501f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    LOG_RTCERR2(RegisterExternalTransport, channel, this);
25020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2503f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2504f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // Enable RTCP (for quality stats and feedback messages)
2505f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  EnableRtcp(channel);
2506f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2507f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // Reset all recv codecs; they will be enabled via SetRecvCodecs.
2508f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  ResetRecvCodecs(channel);
25092ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org
25102ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  // Set RTP header extension for the new channel.
25112ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  SetChannelSendRtpHeaderExtensions(channel, send_extensions_);
2512f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org}
2513f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2514f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.orgbool WebRtcVoiceMediaChannel::DeleteChannel(int channel) {
2515f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (engine()->voe()->network()->DeRegisterExternalTransport(channel) == -1) {
2516f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    LOG_RTCERR1(DeRegisterExternalTransport, channel);
2517f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
2518f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2519f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (engine()->voe()->base()->DeleteChannel(channel) == -1) {
2520f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    LOG_RTCERR1(DeleteChannel, channel);
2521f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    return false;
2522f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
2523f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
25240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
25250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
25260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
25270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
2528f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // If the default channel is already used for sending create a new channel
2529f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // otherwise use the default channel for sending.
2530f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  int channel = GetSendChannelNum(sp.first_ssrc());
2531f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (channel != -1) {
2532f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    LOG(LS_ERROR) << "Stream already exists with ssrc " << sp.first_ssrc();
25330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
25340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
25350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2536f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  bool default_channel_is_available = true;
2537f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  for (ChannelMap::const_iterator iter = send_channels_.begin();
2538f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org       iter != send_channels_.end(); ++iter) {
2539b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    if (IsDefaultChannel(iter->second->channel())) {
2540f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      default_channel_is_available = false;
2541f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      break;
2542f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    }
2543f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
2544f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (default_channel_is_available) {
2545f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    channel = voe_channel();
2546f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  } else {
2547f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // Create a new channel for sending audio data.
254897fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org    channel = engine()->CreateMediaVoiceChannel();
2549f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    if (channel == -1) {
2550f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      LOG_RTCERR0(CreateChannel);
2551f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      return false;
2552f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    }
2553f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2554f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    ConfigureSendChannel(channel);
2555f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
2556f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2557f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // Save the channel to send_channels_, so that RemoveSendStream() can still
2558f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // delete the channel in case failure happens below.
2559b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  webrtc::AudioTransport* audio_transport =
2560b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      engine()->voe()->base()->audio_transport();
2561b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  send_channels_.insert(std::make_pair(
2562b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      sp.first_ssrc(),
2563b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      new WebRtcVoiceChannelRenderer(channel, audio_transport)));
2564f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2565f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // Set the send (local) SSRC.
2566f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // If there are multiple send SSRCs, we can only set the first one here, and
2567f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // the rest of the SSRC(s) need to be set after SetSendCodec has been called
2568f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // (with a codec requires multiple SSRC(s)).
2569f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (engine()->voe()->rtp()->SetLocalSSRC(channel, sp.first_ssrc()) == -1) {
2570f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    LOG_RTCERR2(SetSendSSRC, channel, sp.first_ssrc());
25710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
25720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2573f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2574f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // At this point the channel's local SSRC has been updated. If the channel is
2575f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // the default channel make sure that all the receive channels are updated as
2576f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // well. Receive channels have to have the same SSRC as the default channel in
2577f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // order to send receiver reports with this SSRC.
2578f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (IsDefaultChannel(channel)) {
2579f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    for (ChannelMap::const_iterator it = receive_channels_.begin();
2580f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org         it != receive_channels_.end(); ++it) {
2581f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      // Only update the SSRC for non-default channels.
2582b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      if (!IsDefaultChannel(it->second->channel())) {
2583b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org        if (engine()->voe()->rtp()->SetLocalSSRC(it->second->channel(),
2584f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org                                                 sp.first_ssrc()) != 0) {
2585b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org          LOG_RTCERR2(SetLocalSSRC, it->second->channel(), sp.first_ssrc());
2586f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          return false;
2587f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        }
25887162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      }
25890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
25900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
25910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2592f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (engine()->voe()->rtp()->SetRTCP_CNAME(channel, sp.cname.c_str()) == -1) {
25935462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    LOG_RTCERR2(SetRTCP_CNAME, channel, sp.cname);
25945462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    return false;
25950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
25960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2597952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  // Set the current codecs to be used for the new channel.
2598952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  if (!send_codecs_.empty() && !SetSendCodecs(channel, send_codecs_))
2599f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    return false;
26007162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
2601f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  return ChangeSend(channel, desired_send_);
26020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
26030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
26040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::RemoveSendStream(uint32 ssrc) {
2605f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  ChannelMap::iterator it = send_channels_.find(ssrc);
2606f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (it == send_channels_.end()) {
2607f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
2608f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org                    << " which doesn't exist.";
26090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
26100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
26117162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
2612b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  int channel = it->second->channel();
2613f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  ChangeSend(channel, SEND_NOTHING);
2614f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2615b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // Delete the WebRtcVoiceChannelRenderer object connected to the channel,
2616b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // this will disconnect the audio renderer with the send channel.
2617b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  delete it->second;
2618b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  send_channels_.erase(it);
2619f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2620f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (IsDefaultChannel(channel)) {
2621f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // Do not delete the default channel since the receive channels depend on
2622f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // the default channel, recycle it instead.
2623f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    ChangeSend(channel, SEND_NOTHING);
2624f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  } else {
2625f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // Clean up and delete the send channel.
2626f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    LOG(LS_INFO) << "Removing audio send stream " << ssrc
2627f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org                 << " with VoiceEngine channel #" << channel << ".";
2628f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    if (!DeleteChannel(channel))
2629f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      return false;
2630f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
2631f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
2632f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (send_channels_.empty())
2633f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    ChangeSend(SEND_NOTHING);
26347162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
26350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
26360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
26370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
26380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
26392a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope lock(&receive_channels_cs_);
26400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
26410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!VERIFY(sp.ssrcs.size() == 1))
26420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
26430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 ssrc = sp.first_ssrc();
26440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2645861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org  if (ssrc == 0) {
2646861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org    LOG(LS_WARNING) << "AddRecvStream with 0 ssrc is not supported.";
2647861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org    return false;
2648861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org  }
2649861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org
26507162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  if (receive_channels_.find(ssrc) != receive_channels_.end()) {
26517162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
26520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
26530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
26540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
26557162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  // Reuse default channel for recv stream in non-conference mode call
26567162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  // when the default channel is not being used.
2657b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  webrtc::AudioTransport* audio_transport =
2658b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      engine()->voe()->base()->audio_transport();
26597162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  if (!InConferenceMode() && default_receive_ssrc_ == 0) {
26607162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    LOG(LS_INFO) << "Recv stream " << sp.first_ssrc()
26617162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org                 << " reuse default channel";
26627162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    default_receive_ssrc_ = sp.first_ssrc();
26637162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    receive_channels_.insert(std::make_pair(
2664b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org        default_receive_ssrc_,
2665b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org        new WebRtcVoiceChannelRenderer(voe_channel(), audio_transport)));
26665462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    if (!SetupSharedBweOnChannel(voe_channel())) {
26675462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org      return false;
26685462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    }
26697162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    return SetPlayout(voe_channel(), playout_);
26707162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  }
26717162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
26720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Create a new channel for receiving audio data.
267397fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org  int channel = engine()->CreateMediaVoiceChannel();
26740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (channel == -1) {
26750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_RTCERR0(CreateChannel);
26760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
26770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
26780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2679861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org  if (!ConfigureRecvChannel(channel)) {
2680861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org    DeleteChannel(channel);
2681861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org    return false;
2682861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org  }
2683861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org
2684861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org  receive_channels_.insert(
2685b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      std::make_pair(
2686b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org          ssrc, new WebRtcVoiceChannelRenderer(channel, audio_transport)));
2687861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org
2688861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org  LOG(LS_INFO) << "New audio stream " << ssrc
2689861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org               << " registered to VoiceEngine channel #"
2690861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org               << channel << ".";
2691861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org  return true;
2692861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org}
2693861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org
2694861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.orgbool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) {
26950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Configure to use external transport, like our default channel.
26960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (engine()->voe()->network()->RegisterExternalTransport(
26970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          channel, *this) == -1) {
26980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_RTCERR2(SetExternalTransport, channel, this);
26990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
27000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
27010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
27020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Use the same SSRC as our default channel (so the RTCP reports are correct).
27038485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org  unsigned int send_ssrc = 0;
27040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  webrtc::VoERTP_RTCP* rtp = engine()->voe()->rtp();
27050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (rtp->GetLocalSSRC(voe_channel(), send_ssrc) == -1) {
27068485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org    LOG_RTCERR1(GetSendSSRC, channel);
27070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
27080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
27090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (rtp->SetLocalSSRC(channel, send_ssrc) == -1) {
27108485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org    LOG_RTCERR1(SetSendSSRC, channel);
27110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
27120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
27130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
27140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Use the same recv payload types as our default channel.
27150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ResetRecvCodecs(channel);
27160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!recv_codecs_.empty()) {
27170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (std::vector<AudioCodec>::const_iterator it = recv_codecs_.begin();
27180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        it != recv_codecs_.end(); ++it) {
27190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      webrtc::CodecInst voe_codec;
27200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (engine()->FindWebRtcCodec(*it, &voe_codec)) {
27210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        voe_codec.pltype = it->id;
27220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        voe_codec.rate = 0;  // Needed to make GetRecPayloadType work for ISAC
27230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (engine()->voe()->codec()->GetRecPayloadType(
27240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            voe_channel(), voe_codec) != -1) {
27250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          if (engine()->voe()->codec()->SetRecPayloadType(
27260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org              channel, voe_codec) == -1) {
27270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec));
27280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            return false;
27290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          }
27300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
27310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
27320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
27330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
27340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
27357162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  if (InConferenceMode()) {
27367162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    // To be in par with the video, voe_channel() is not used for receiving in
27377162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    // a conference call.
27387162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    if (receive_channels_.empty() && default_receive_ssrc_ == 0 && playout_) {
27397162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      // This is the first stream in a multi user meeting. We can now
27407162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      // disable playback of the default stream. This since the default
27417162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      // stream will probably have received some initial packets before
27427162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      // the new stream was added. This will mean that the CN state from
27437162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      // the default channel will be mixed in with the other streams
27447162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      // throughout the whole meeting, which might be disturbing.
27457162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      LOG(LS_INFO) << "Disabling playback on the default voice channel";
27467162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      SetPlayout(voe_channel(), false);
27477162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    }
27480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2749952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org  SetNack(channel, nack_enabled_);
27500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
27512ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  // Set RTP header extension for the new channel.
27522ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  if (!SetChannelRecvRtpHeaderExtensions(channel, receive_extensions_)) {
27532ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    return false;
27542ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  }
27552ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org
27565462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  // Set up channel to be able to forward incoming packets to video engine BWE.
27575462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  if (!SetupSharedBweOnChannel(channel)) {
27585462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    return false;
27595462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  }
27605462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org
27610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return SetPlayout(channel, playout_);
27620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
27630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
27640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32 ssrc) {
27652a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope lock(&receive_channels_cs_);
27667162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  ChannelMap::iterator it = receive_channels_.find(ssrc);
2767f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (it == receive_channels_.end()) {
2768f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
2769f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org                    << " which doesn't exist.";
27707162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    return false;
2771f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
27720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2773b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // Delete the WebRtcVoiceChannelRenderer object connected to the channel, this
2774b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // will disconnect the audio renderer with the receive channel.
2775b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  // Cache the channel before the deletion.
2776b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  const int channel = it->second->channel();
2777b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  delete it->second;
2778b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  receive_channels_.erase(it);
2779b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org
27807162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  if (ssrc == default_receive_ssrc_) {
2781b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    ASSERT(IsDefaultChannel(channel));
27827162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    // Recycle the default channel is for recv stream.
27837162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    if (playout_)
27847162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      SetPlayout(voe_channel(), false);
27857162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
27867162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    default_receive_ssrc_ = 0;
27877162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    return true;
27887162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  }
27897162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
27907162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  LOG(LS_INFO) << "Removing audio stream " << ssrc
2791b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org               << " with VoiceEngine channel #" << channel << ".";
2792b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  if (!DeleteChannel(channel))
27937162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    return false;
27947162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
27957162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  bool enable_default_channel_playout = false;
27967162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  if (receive_channels_.empty()) {
27977162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    // The last stream was removed. We can now enable the default
27987162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    // channel for new channels to be played out immediately without
27997162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    // waiting for AddStream messages.
28007162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    // We do this for both conference mode and non-conference mode.
28017162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    // TODO(oja): Does the default channel still have it's CN state?
28027162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    enable_default_channel_playout = true;
28037162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  }
28047162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  if (!InConferenceMode() && receive_channels_.size() == 1 &&
28057162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      default_receive_ssrc_ != 0) {
28067162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    // Only the default channel is active, enable the playout on default
28077162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    // channel.
28087162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    enable_default_channel_playout = true;
28097162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  }
28107162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  if (enable_default_channel_playout && playout_) {
28117162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    LOG(LS_INFO) << "Enabling playback on the default voice channel";
28127162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    SetPlayout(voe_channel(), true);
28137162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  }
28147162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
28157162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  return true;
28167162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org}
28177162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
28187162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetRemoteRenderer(uint32 ssrc,
28197162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org                                                AudioRenderer* renderer) {
28207162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  ChannelMap::iterator it = receive_channels_.find(ssrc);
28217162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  if (it == receive_channels_.end()) {
28227162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    if (renderer) {
28237162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      // Return an error if trying to set a valid renderer with an invalid ssrc.
2824f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      LOG(LS_ERROR) << "SetRemoteRenderer failed with ssrc "<< ssrc;
28250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
28260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
28270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
28287162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    // The channel likely has gone away, do nothing.
28297162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    return true;
28307162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  }
28317162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
2832b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  if (renderer)
2833b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    it->second->Start(renderer);
2834b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  else
2835b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    it->second->Stop();
28367162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
28370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
28380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
28390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
28407162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetLocalRenderer(uint32 ssrc,
28417162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org                                               AudioRenderer* renderer) {
2842f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  ChannelMap::iterator it = send_channels_.find(ssrc);
2843f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (it == send_channels_.end()) {
2844f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    if (renderer) {
2845f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      // Return an error if trying to set a valid renderer with an invalid ssrc.
2846f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      LOG(LS_ERROR) << "SetLocalRenderer failed with ssrc "<< ssrc;
2847f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      return false;
2848f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    }
28497162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
2850f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // The channel likely has gone away, do nothing.
2851f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    return true;
28527162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  }
28530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2854b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  if (renderer)
2855b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    it->second->Start(renderer);
2856b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org  else
2857b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    it->second->Stop();
28587162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org
28590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
28600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
28610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
28620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::GetActiveStreams(
28630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    AudioInfo::StreamList* actives) {
28647162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  // In conference mode, the default channel should not be in
28657162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  // |receive_channels_|.
28660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  actives->clear();
28677162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  for (ChannelMap::iterator it = receive_channels_.begin();
28687162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org       it != receive_channels_.end(); ++it) {
2869b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    int level = GetOutputLevel(it->second->channel());
28700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (level > 0) {
28710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      actives->push_back(std::make_pair(it->first, level));
28720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
28730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
28740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
28750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
28760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
28770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceMediaChannel::GetOutputLevel() {
28780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // return the highest output level of all streams
28790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int highest = GetOutputLevel(voe_channel());
28807162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  for (ChannelMap::iterator it = receive_channels_.begin();
28817162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org       it != receive_channels_.end(); ++it) {
2882b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    int level = GetOutputLevel(it->second->channel());
28832a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    highest = rtc::_max(level, highest);
28840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
28850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return highest;
28860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
28870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
28880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceMediaChannel::GetTimeSinceLastTyping() {
28890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int ret;
28900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (engine()->voe()->processing()->TimeSinceLastTyping(ret) == -1) {
28910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // In case of error, log the info and continue
28920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_RTCERR0(TimeSinceLastTyping);
28930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ret = -1;
28940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
28950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ret *= 1000;  // We return ms, webrtc returns seconds.
28960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
28970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ret;
28980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
28990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
29000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceMediaChannel::SetTypingDetectionParameters(int time_window,
29010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int cost_per_typing, int reporting_threshold, int penalty_decay,
29020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int type_event_delay) {
29030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (engine()->voe()->processing()->SetTypingDetectionParameters(
29040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          time_window, cost_per_typing,
29050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          reporting_threshold, penalty_decay, type_event_delay) == -1) {
29060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // In case of error, log the info and continue
29070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_RTCERR5(SetTypingDetectionParameters, time_window,
29080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                cost_per_typing, reporting_threshold, penalty_decay,
29090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                type_event_delay);
29100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
29110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
29120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
29130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetOutputScaling(
29140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 ssrc, double left, double right) {
29152a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope lock(&receive_channels_cs_);
29160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Collect the channels to scale the output volume.
29170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<int> channels;
29180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (0 == ssrc) {  // Collect all channels, including the default one.
29197162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    // Default channel is not in receive_channels_ if it is not being used for
29207162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    // playout.
29217162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    if (default_receive_ssrc_ == 0)
29227162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org      channels.push_back(voe_channel());
29237162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    for (ChannelMap::const_iterator it = receive_channels_.begin();
29247162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org         it != receive_channels_.end(); ++it) {
2925b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      channels.push_back(it->second->channel());
29260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
29270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {  // Collect only the channel of the specified ssrc.
29280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int channel = GetReceiveChannelNum(ssrc);
29290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (-1 == channel) {
29300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_WARNING) << "Cannot find channel for ssrc:" << ssrc;
29310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
29320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
29330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    channels.push_back(channel);
29340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
29350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
29360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Scale the output volume for the collected channels. We first normalize to
29370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // scale the volume and then set the left and right pan.
29382a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  float scale = static_cast<float>(rtc::_max(left, right));
29390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (scale > 0.0001f) {
29400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    left /= scale;
29410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    right /= scale;
29420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
29430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<int>::const_iterator it = channels.begin();
29440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      it != channels.end(); ++it) {
29450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (-1 == engine()->voe()->volume()->SetChannelOutputVolumeScaling(
29460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        *it, scale)) {
29470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR2(SetChannelOutputVolumeScaling, *it, scale);
29480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
29490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
29500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (-1 == engine()->voe()->volume()->SetOutputVolumePan(
29510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        *it, static_cast<float>(left), static_cast<float>(right))) {
29520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR3(SetOutputVolumePan, *it, left, right);
29530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Do not return if fails. SetOutputVolumePan is not available for all
29540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // pltforms.
29550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
29560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_INFO) << "SetOutputScaling to left=" << left * scale
29570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 << " right=" << right * scale
29580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 << " for channel " << *it << " and ssrc " << ssrc;
29590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
29600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
29610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
29620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
29630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::GetOutputScaling(
29640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 ssrc, double* left, double* right) {
29650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!left || !right) return false;
29660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
29672a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope lock(&receive_channels_cs_);
29680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Determine which channel based on ssrc.
29690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int channel = (0 == ssrc) ? voe_channel() : GetReceiveChannelNum(ssrc);
29700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (channel == -1) {
29710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Cannot find channel for ssrc:" << ssrc;
29720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
29730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
29740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
29750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  float scaling;
29760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (-1 == engine()->voe()->volume()->GetChannelOutputVolumeScaling(
29770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      channel, scaling)) {
29780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_RTCERR2(GetChannelOutputVolumeScaling, channel, scaling);
29790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
29800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
29810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
29820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  float left_pan;
29830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  float right_pan;
29840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (-1 == engine()->voe()->volume()->GetOutputVolumePan(
29850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      channel, left_pan, right_pan)) {
29860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_RTCERR3(GetOutputVolumePan, channel, left_pan, right_pan);
29870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // If GetOutputVolumePan fails, we use the default left and right pan.
29880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    left_pan = 1.0f;
29890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    right_pan = 1.0f;
29900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
29910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
29920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *left = scaling * left_pan;
29930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *right = scaling * right_pan;
29940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
29950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
29960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
29970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetRingbackTone(const char *buf, int len) {
29980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ringback_tone_.reset(new WebRtcSoundclipStream(buf, len));
29990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
30000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
30010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
30020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::PlayRingbackTone(uint32 ssrc,
30030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                             bool play, bool loop) {
30040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!ringback_tone_) {
30050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
30060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
30070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
30080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // The voe file api is not available in chrome.
30090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!engine()->voe()->file()) {
30100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
30110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
30120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
30130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Determine which VoiceEngine channel to play on.
30140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int channel = (ssrc == 0) ? voe_channel() : GetReceiveChannelNum(ssrc);
30150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (channel == -1) {
30160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
30170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
30180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
30190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Make sure the ringtone is cued properly, and play it out.
30200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (play) {
30210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ringback_tone_->set_loop(loop);
30220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ringback_tone_->Rewind();
30230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (engine()->voe()->file()->StartPlayingFileLocally(channel,
30240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ringback_tone_.get()) == -1) {
30250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR2(StartPlayingFileLocally, channel, ringback_tone_.get());
30260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_ERROR) << "Unable to start ringback tone";
30270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
30280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
30290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ringback_channels_.insert(channel);
30300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_INFO) << "Started ringback on channel " << channel;
30310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
30320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (engine()->voe()->file()->IsPlayingFileLocally(channel) == 1 &&
30330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        engine()->voe()->file()->StopPlayingFileLocally(channel) == -1) {
30340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR1(StopPlayingFileLocally, channel);
30350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
30360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
30370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_INFO) << "Stopped ringback on channel " << channel;
30380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ringback_channels_.erase(channel);
30390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
30400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
30410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
30420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
30430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
30440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::CanInsertDtmf() {
30450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return dtmf_allowed_;
30460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
30470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
30480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::InsertDtmf(uint32 ssrc, int event,
30490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                         int duration, int flags) {
30500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!dtmf_allowed_) {
30510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
30520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
30530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
30540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Send the event.
30550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (flags & cricket::DF_SEND) {
3056952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org    int channel = -1;
3057952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org    if (ssrc == 0) {
3058952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      bool default_channel_is_inuse = false;
3059952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      for (ChannelMap::const_iterator iter = send_channels_.begin();
3060952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org           iter != send_channels_.end(); ++iter) {
3061b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org        if (IsDefaultChannel(iter->second->channel())) {
3062952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org          default_channel_is_inuse = true;
3063952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org          break;
3064952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org        }
3065952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      }
3066952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      if (default_channel_is_inuse) {
3067952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org        channel = voe_channel();
3068952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      } else if (!send_channels_.empty()) {
3069b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org        channel = send_channels_.begin()->second->channel();
3070952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      }
3071952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org    } else {
3072952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org      channel = GetSendChannelNum(ssrc);
3073952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org    }
3074f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    if (channel == -1) {
30750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_WARNING) << "InsertDtmf - The specified ssrc "
30760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      << ssrc << " is not in use.";
30770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
30780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
30790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Send DTMF using out-of-band DTMF. ("true", as 3rd arg)
3080f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    if (engine()->voe()->dtmf()->SendTelephoneEvent(
3081f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org            channel, event, true, duration) == -1) {
3082f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      LOG_RTCERR4(SendTelephoneEvent, channel, event, true, duration);
30830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
30840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
30850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
30860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
30870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Play the event.
30880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (flags & cricket::DF_PLAY) {
30890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Play DTMF tone locally.
30900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (engine()->voe()->dtmf()->PlayDtmfTone(event, duration) == -1) {
30910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR2(PlayDtmfTone, event, duration);
30920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
30930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
30940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
30950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
30960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
30970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
30980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3099f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.orgvoid WebRtcVoiceMediaChannel::OnPacketReceived(
31002a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
31010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Pick which channel to send this packet to. If this packet doesn't match
31020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // any multiplexed streams, just send it to the default channel. Otherwise,
31030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // send it to the specific decoder instance for that stream.
31040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int which_channel = GetReceiveChannelNum(
31050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ParseSsrc(packet->data(), packet->length(), false));
31060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (which_channel == -1) {
31070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    which_channel = voe_channel();
31080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
31090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
31100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Stop any ringback that might be playing on the channel.
31110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // It's possible the ringback has already stopped, ih which case we'll just
31120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // use the opportunity to remove the channel from ringback_channels_.
31130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (engine()->voe()->file()) {
31140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::set<int>::iterator it = ringback_channels_.find(which_channel);
31150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (it != ringback_channels_.end()) {
31160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (engine()->voe()->file()->IsPlayingFileLocally(
31170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          which_channel) == 1) {
31180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        engine()->voe()->file()->StopPlayingFileLocally(which_channel);
31190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG(LS_INFO) << "Stopped ringback on channel " << which_channel
31200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                     << " due to incoming media";
31210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
31220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ringback_channels_.erase(which_channel);
31230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
31240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
31250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
31260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Pass it off to the decoder.
31271a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org  engine()->voe()->network()->ReceivedRTPPacket(
31281a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org      which_channel,
31291a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org      packet->data(),
31305462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org      static_cast<unsigned int>(packet->length()),
31315462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org      webrtc::PacketTime(packet_time.timestamp, packet_time.not_before));
31320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
31330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3134f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.orgvoid WebRtcVoiceMediaChannel::OnRtcpReceived(
31352a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
3136f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // Sending channels need all RTCP packets with feedback information.
3137f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // Even sender reports can contain attached report blocks.
3138f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // Receiving channels need sender reports in order to create
3139f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // correct receiver reports.
3140f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  int type = 0;
3141f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (!GetRtcpType(packet->data(), packet->length(), &type)) {
3142f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    LOG(LS_WARNING) << "Failed to parse type from received RTCP packet";
3143f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    return;
3144f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
3145f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
3146f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // If it is a sender report, find the channel that is listening.
3147f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  bool has_sent_to_default_channel = false;
3148f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (type == kRtcpTypeSR) {
3149f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    int which_channel = GetReceiveChannelNum(
3150f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        ParseSsrc(packet->data(), packet->length(), true));
3151f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    if (which_channel != -1) {
3152f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      engine()->voe()->network()->ReceivedRTCPPacket(
3153f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          which_channel,
3154f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          packet->data(),
3155f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          static_cast<unsigned int>(packet->length()));
3156f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
3157f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      if (IsDefaultChannel(which_channel))
3158f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        has_sent_to_default_channel = true;
3159f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    }
3160f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
3161f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
3162f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // SR may continue RR and any RR entry may correspond to any one of the send
3163f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // channels. So all RTCP packets must be forwarded all send channels. VoE
3164f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // will filter out RR internally.
3165f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  for (ChannelMap::iterator iter = send_channels_.begin();
3166f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org       iter != send_channels_.end(); ++iter) {
3167f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // Make sure not sending the same packet to default channel more than once.
3168b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    if (IsDefaultChannel(iter->second->channel()) &&
3169b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org        has_sent_to_default_channel)
3170f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      continue;
31710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3172f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    engine()->voe()->network()->ReceivedRTCPPacket(
3173b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org        iter->second->channel(),
3174f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        packet->data(),
3175f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        static_cast<unsigned int>(packet->length()));
3176f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
31770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
31780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
31790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::MuteStream(uint32 ssrc, bool muted) {
3180f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  int channel = (ssrc == 0) ? voe_channel() : GetSendChannelNum(ssrc);
3181f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (channel == -1) {
31820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
31830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
31840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3185f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (engine()->voe()->volume()->SetInputMute(channel, muted) == -1) {
3186f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    LOG_RTCERR2(SetInputMute, channel, muted);
31870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
31880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
31897663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org  // We set the AGC to mute state only when all the channels are muted.
31907663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org  // This implementation is not ideal, instead we should signal the AGC when
31917663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org  // the mic channel is muted/unmuted. We can't do it today because there
31927663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org  // is no good way to know which stream is mapping to the mic channel.
31937663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org  bool all_muted = muted;
31947663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org  for (ChannelMap::const_iterator iter = send_channels_.begin();
31957663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org       iter != send_channels_.end() && all_muted; ++iter) {
31967663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org    if (engine()->voe()->volume()->GetInputMute(iter->second->channel(),
31977663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org                                                all_muted)) {
31987663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org      LOG_RTCERR1(GetInputMute, iter->second->channel());
31997663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org      return false;
32007663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org    }
32017663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org  }
32027663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org
32037663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org  webrtc::AudioProcessing* ap = engine()->voe()->base()->audio_processing();
32047663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org  if (ap)
32057663c27fdfb3df16d08afced5d8b08026e91c05dbuildbot@webrtc.org    ap->set_output_will_be_muted(all_muted);
32060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
32070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
32080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3209f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.orgbool WebRtcVoiceMediaChannel::SetStartSendBandwidth(int bps) {
3210f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  // TODO(andresp): Add support for setting an independent start bandwidth when
3211f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  // bandwidth estimation is enabled for voice engine.
3212f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  return false;
3213f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org}
32140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3215f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.orgbool WebRtcVoiceMediaChannel::SetMaxSendBandwidth(int bps) {
3216f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  LOG(LS_INFO) << "WebRtcVoiceMediaChanne::SetSendBandwidth.";
3217cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org
3218f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  return SetSendBandwidthInternal(bps);
3219cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org}
3220cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org
3221f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.orgbool WebRtcVoiceMediaChannel::SetSendBandwidthInternal(int bps) {
3222f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendBandwidthInternal.";
3223f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org
3224f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  send_bw_setting_ = true;
3225f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  send_bw_bps_ = bps;
3226cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org
32270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!send_codec_) {
3228cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org    LOG(LS_INFO) << "The send codec has not been set up yet. "
3229cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org                 << "The send bandwidth setting will be applied later.";
3230cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org    return true;
32310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
32320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
32330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Bandwidth is auto by default.
3234f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by
3235f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  // SetMaxSendBandwith(0), the second call removes the previous limit.
3236f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  if (bps <= 0)
32370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
32380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
32390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  webrtc::CodecInst codec = *send_codec_;
32400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool is_multi_rate = IsCodecMultiRate(codec);
32410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
32420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (is_multi_rate) {
32430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // If codec is multi-rate then just set the bitrate.
32440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    codec.rate = bps;
32450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!SetSendCodec(codec)) {
32460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_INFO) << "Failed to set codec " << codec.plname
32470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << " to bitrate " << bps << " bps.";
32480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
32490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
32500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
32510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
32520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // If codec is not multi-rate and |bps| is less than the fixed bitrate
32530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // then fail. If codec is not multi-rate and |bps| exceeds or equal the
32540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // fixed bitrate then ignore.
32550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (bps < codec.rate) {
32560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_INFO) << "Failed to set codec " << codec.plname
32570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << " to bitrate " << bps << " bps"
32580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   << ", requires at least " << codec.rate << " bps.";
32590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
32600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
32610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
32620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
32630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
32640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
32650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
32660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool echo_metrics_on = false;
32670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // These can take on valid negative values, so use the lowest possible level
32680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // as default rather than -1.
3269f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  int echo_return_loss = -100;
3270f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  int echo_return_loss_enhancement = -100;
32710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // These can also be negative, but in practice -1 is only used to signal
32720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // insufficient data, since the resolution is limited to multiples of 4 ms.
3273f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  int echo_delay_median_ms = -1;
3274f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  int echo_delay_std_ms = -1;
3275f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (engine()->voe()->processing()->GetEcMetricsStatus(
3276f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          echo_metrics_on) != -1 && echo_metrics_on) {
32770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // TODO(ajm): we may want to use VoECallReport::GetEchoMetricsSummary
32780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // here, but it appears to be unsuitable currently. Revisit after this is
32790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // investigated: http://b/issue?id=5666755
32800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int erl, erle, rerl, anlp;
3281f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    if (engine()->voe()->processing()->GetEchoMetrics(
3282f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org            erl, erle, rerl, anlp) != -1) {
3283f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      echo_return_loss = erl;
3284f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      echo_return_loss_enhancement = erle;
32850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
32860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
32870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int median, std;
32880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (engine()->voe()->processing()->GetEcDelayMetrics(median, std) != -1) {
3289f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      echo_delay_median_ms = median;
3290f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      echo_delay_std_ms = std;
32910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
32920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
32930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3294f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  webrtc::CallStatistics cs;
3295f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  unsigned int ssrc;
3296f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  webrtc::CodecInst codec;
3297f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  unsigned int level;
3298f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
3299f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  for (ChannelMap::const_iterator channel_iter = send_channels_.begin();
3300f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org       channel_iter != send_channels_.end(); ++channel_iter) {
3301b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    const int channel = channel_iter->second->channel();
3302f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
3303f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // Fill in the sender info, based on what we know, and what the
3304f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // remote side told us it got from its RTCP report.
3305f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    VoiceSenderInfo sinfo;
3306f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
3307f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    if (engine()->voe()->rtp()->GetRTCPStatistics(channel, cs) == -1 ||
3308f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        engine()->voe()->rtp()->GetLocalSSRC(channel, ssrc) == -1) {
3309f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      continue;
3310f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    }
3311f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
331297fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org    sinfo.add_ssrc(ssrc);
3313f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    sinfo.codec_name = send_codec_.get() ? send_codec_->plname : "";
3314f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    sinfo.bytes_sent = cs.bytesSent;
3315f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    sinfo.packets_sent = cs.packetsSent;
3316f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // RTT isn't known until a RTCP report is received. Until then, VoiceEngine
3317f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // returns 0 to indicate an error value.
3318f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    sinfo.rtt_ms = (cs.rttMs > 0) ? cs.rttMs : -1;
3319f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
3320f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // Get data from the last remote RTCP report. Use default values if no data
3321f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // available.
3322f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    sinfo.fraction_lost = -1.0;
3323f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    sinfo.jitter_ms = -1;
3324f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    sinfo.packets_lost = -1;
3325f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    sinfo.ext_seqnum = -1;
3326f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    std::vector<webrtc::ReportBlock> receive_blocks;
3327f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    if (engine()->voe()->rtp()->GetRemoteRTCPReportBlocks(
3328f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org            channel, &receive_blocks) != -1 &&
3329f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        engine()->voe()->codec()->GetSendCodec(channel, codec) != -1) {
3330f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      std::vector<webrtc::ReportBlock>::iterator iter;
3331f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      for (iter = receive_blocks.begin(); iter != receive_blocks.end();
3332f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org           ++iter) {
3333f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        // Lookup report for send ssrc only.
333497fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org        if (iter->source_SSRC == sinfo.ssrc()) {
3335f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          // Convert Q8 to floating point.
3336f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          sinfo.fraction_lost = static_cast<float>(iter->fraction_lost) / 256;
3337f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          // Convert samples to milliseconds.
3338f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          if (codec.plfreq / 1000 > 0) {
3339f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org            sinfo.jitter_ms = iter->interarrival_jitter / (codec.plfreq / 1000);
3340f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          }
3341f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          sinfo.packets_lost = iter->cumulative_num_packets_lost;
3342f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          sinfo.ext_seqnum = iter->extended_highest_sequence_number;
3343f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          break;
3344f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        }
3345f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      }
3346f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    }
3347f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
3348f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // Local speech level.
3349f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    sinfo.audio_level = (engine()->voe()->volume()->
3350f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        GetSpeechInputLevelFullRange(level) != -1) ? level : -1;
3351f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
3352f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // TODO(xians): We are injecting the same APM logging to all the send
3353f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // channels here because there is no good way to know which send channel
3354f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // is using the APM. The correct fix is to allow the send channels to have
3355f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // their own APM so that we can feed the correct APM logging to different
3356f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // send channels. See issue crbug/264611 .
3357f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    sinfo.echo_return_loss = echo_return_loss;
3358f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    sinfo.echo_return_loss_enhancement = echo_return_loss_enhancement;
3359f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    sinfo.echo_delay_median_ms = echo_delay_median_ms;
3360f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    sinfo.echo_delay_std_ms = echo_delay_std_ms;
33615528070a0c76057a000b877fc56ca4180ad2087bmallinath@webrtc.org    // TODO(ajm): Re-enable this metric once we have a reliable implementation.
33625528070a0c76057a000b877fc56ca4180ad2087bmallinath@webrtc.org    sinfo.aec_quality_min = -1;
33634ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org    sinfo.typing_noise_detected = typing_noise_detected_;
3364f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
3365f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    info->senders.push_back(sinfo);
3366f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
33670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
33687162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  // Build the list of receivers, one for each receiving channel, or 1 in
33697162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  // a 1:1 call.
33700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<int> channels;
33717162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  for (ChannelMap::const_iterator it = receive_channels_.begin();
33727162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org       it != receive_channels_.end(); ++it) {
3373b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    channels.push_back(it->second->channel());
33740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
33750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (channels.empty()) {
33760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    channels.push_back(voe_channel());
33770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
33780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
33790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Get the SSRC and stats for each receiver, based on our own calculations.
33800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<int>::const_iterator it = channels.begin();
33810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != channels.end(); ++it) {
33820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    memset(&cs, 0, sizeof(cs));
33830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (engine()->voe()->rtp()->GetRemoteSSRC(*it, ssrc) != -1 &&
33840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        engine()->voe()->rtp()->GetRTCPStatistics(*it, cs) != -1 &&
33850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        engine()->voe()->codec()->GetRecCodec(*it, codec) != -1) {
33860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      VoiceReceiverInfo rinfo;
338797fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org      rinfo.add_ssrc(ssrc);
33880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      rinfo.bytes_rcvd = cs.bytesReceived;
33890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      rinfo.packets_rcvd = cs.packetsReceived;
33900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // The next four fields are from the most recently sent RTCP report.
33910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Convert Q8 to floating point.
33920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      rinfo.fraction_lost = static_cast<float>(cs.fractionLost) / (1 << 8);
33930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      rinfo.packets_lost = cs.cumulativeLost;
33940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      rinfo.ext_seqnum = cs.extendedMax;
3395842c369caaf7ab0115e101686ee5640a289da0e8buildbot@webrtc.org#ifdef USE_WEBRTC_DEV_BRANCH
3396842c369caaf7ab0115e101686ee5640a289da0e8buildbot@webrtc.org      rinfo.capture_start_ntp_time_ms = cs.capture_start_ntp_time_ms_;
3397842c369caaf7ab0115e101686ee5640a289da0e8buildbot@webrtc.org#endif
3398ec0b1b83d70e08f3bd47940d33ad69cb8bb0878fbuildbot@webrtc.org      if (codec.pltype != -1) {
3399ec0b1b83d70e08f3bd47940d33ad69cb8bb0878fbuildbot@webrtc.org        rinfo.codec_name = codec.plname;
3400ec0b1b83d70e08f3bd47940d33ad69cb8bb0878fbuildbot@webrtc.org      }
34010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Convert samples to milliseconds.
34020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (codec.plfreq / 1000 > 0) {
34030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        rinfo.jitter_ms = cs.jitterSamples / (codec.plfreq / 1000);
34040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
34050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
34060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Get jitter buffer and total delay (alg + jitter + playout) stats.
34070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      webrtc::NetworkStatistics ns;
34080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (engine()->voe()->neteq() &&
34090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          engine()->voe()->neteq()->GetNetworkStatistics(
34100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org              *it, ns) != -1) {
34110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        rinfo.jitter_buffer_ms = ns.currentBufferSize;
34120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        rinfo.jitter_buffer_preferred_ms = ns.preferredBufferSize;
34130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        rinfo.expand_rate =
34141a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org            static_cast<float>(ns.currentExpandRate) / (1 << 14);
34150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
341654caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org
341754caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org      webrtc::AudioDecodingCallStats ds;
341854caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org      if (engine()->voe()->neteq() &&
341954caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org          engine()->voe()->neteq()->GetDecodingCallStatistics(
342054caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org              *it, &ds) != -1) {
342154caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org        rinfo.decoding_calls_to_silence_generator =
342254caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org            ds.calls_to_silence_generator;
342354caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org        rinfo.decoding_calls_to_neteq = ds.calls_to_neteq;
342454caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org        rinfo.decoding_normal = ds.decoded_normal;
342554caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org        rinfo.decoding_plc = ds.decoded_plc;
342654caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org        rinfo.decoding_cng = ds.decoded_cng;
342754caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org        rinfo.decoding_plc_cng = ds.decoded_plc_cng;
342854caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org      }
342954caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org
34300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (engine()->voe()->sync()) {
343119da4659bfe1cd99b6b1476cae9bc74e99e0b09dsergeyu@chromium.org        int jitter_buffer_delay_ms = 0;
34320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        int playout_buffer_delay_ms = 0;
34330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        engine()->voe()->sync()->GetDelayEstimate(
343419da4659bfe1cd99b6b1476cae9bc74e99e0b09dsergeyu@chromium.org            *it, &jitter_buffer_delay_ms, &playout_buffer_delay_ms);
343519da4659bfe1cd99b6b1476cae9bc74e99e0b09dsergeyu@chromium.org        rinfo.delay_estimate_ms = jitter_buffer_delay_ms +
343619da4659bfe1cd99b6b1476cae9bc74e99e0b09dsergeyu@chromium.org            playout_buffer_delay_ms;
34370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
34380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
34390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Get speech level.
34400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      rinfo.audio_level = (engine()->voe()->volume()->
34410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          GetSpeechOutputLevelFullRange(*it, level) != -1) ? level : -1;
34420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      info->receivers.push_back(rinfo);
34430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
34440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
34450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
34460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
34470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
34480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
34490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceMediaChannel::GetLastMediaError(
34500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32* ssrc, VoiceMediaChannel::Error* error) {
34510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(ssrc != NULL);
34520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(error != NULL);
34530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  FindSsrc(voe_channel(), ssrc);
34540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *error = WebRtcErrorToChannelError(GetLastEngineError());
34550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
34560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
34570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::FindSsrc(int channel_num, uint32* ssrc) {
34582a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope lock(&receive_channels_cs_);
34590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(ssrc != NULL);
3460f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (channel_num == -1 && send_ != SEND_NOTHING) {
34610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Sometimes the VoiceEngine core will throw error with channel_num = -1.
34620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // This means the error is not limited to a specific channel.  Signal the
34630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // message using ssrc=0.  If the current channel is sending, use this
34640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // channel for sending the message.
34650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    *ssrc = 0;
34660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
34670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
3468f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    // Check whether this is a sending channel.
3469f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    for (ChannelMap::const_iterator it = send_channels_.begin();
3470f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org         it != send_channels_.end(); ++it) {
3471b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      if (it->second->channel() == channel_num) {
3472f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        // This is a sending channel.
3473f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        uint32 local_ssrc = 0;
3474f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        if (engine()->voe()->rtp()->GetLocalSSRC(
3475f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org                channel_num, local_ssrc) != -1) {
3476f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org          *ssrc = local_ssrc;
3477f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        }
3478f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org        return true;
3479f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      }
3480f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    }
3481f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
34820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Check whether this is a receiving channel.
34837162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org    for (ChannelMap::const_iterator it = receive_channels_.begin();
34847162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org        it != receive_channels_.end(); ++it) {
3485b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org      if (it->second->channel() == channel_num) {
34860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        *ssrc = it->first;
34870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        return true;
34880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
34890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
34900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
34910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return false;
34920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
34930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
34940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceMediaChannel::OnError(uint32 ssrc, int error) {
34954ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org  if (error == VE_TYPING_NOISE_WARNING) {
34964ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org    typing_noise_detected_ = true;
34974ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org  } else if (error == VE_TYPING_NOISE_OFF_WARNING) {
34984ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org    typing_noise_detected_ = false;
34994ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org  }
35000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalMediaError(ssrc, WebRtcErrorToChannelError(error));
35010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
35020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
35030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceMediaChannel::GetOutputLevel(int channel) {
35040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  unsigned int ulevel;
35050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int ret =
35060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      engine()->voe()->volume()->GetSpeechOutputLevel(channel, ulevel);
35070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return (ret == 0) ? static_cast<int>(ulevel) : -1;
35080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
35090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
35100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceMediaChannel::GetReceiveChannelNum(uint32 ssrc) {
35117162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  ChannelMap::iterator it = receive_channels_.find(ssrc);
35127162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org  if (it != receive_channels_.end())
3513b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    return it->second->channel();
35140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return (ssrc == default_receive_ssrc_) ?  voe_channel() : -1;
35150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
35160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
35170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceMediaChannel::GetSendChannelNum(uint32 ssrc) {
3518f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  ChannelMap::iterator it = send_channels_.find(ssrc);
3519f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (it != send_channels_.end())
3520b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org    return it->second->channel();
3521f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
3522f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  return -1;
35230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
35240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
35255462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.orgbool WebRtcVoiceMediaChannel::SetupSharedBandwidthEstimation(
35265462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    webrtc::VideoEngine* vie, int vie_channel) {
35275462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  shared_bwe_vie_ = vie;
35285462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  shared_bwe_vie_channel_ = vie_channel;
35295462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org
35305462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  if (!SetupSharedBweOnChannel(voe_channel())) {
35315462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    return false;
35325462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  }
35335462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  for (ChannelMap::iterator it = receive_channels_.begin();
35345462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org      it != receive_channels_.end(); ++it) {
35355462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    if (!SetupSharedBweOnChannel(it->second->channel())) {
35365462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org      return false;
35375462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    }
35385462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  }
35395462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  return true;
35405462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org}
35415462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org
35420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec,
35430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::vector<AudioCodec>& all_codecs, webrtc::CodecInst* send_codec) {
35440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Get the RED encodings from the parameter with no name. This may
35450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // change based on what is discussed on the Jingle list.
35460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // The encoding parameter is of the form "a/b"; we only support where
35470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // a == b. Verify this and parse out the value into red_pt.
35480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If the parameter value is absent (as it will be until we wire up the
35490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // signaling of this message), use the second codec specified (i.e. the
35500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // one after "red") as the encoding parameter.
35510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int red_pt = -1;
35520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string red_params;
35530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CodecParameterMap::const_iterator it = red_codec.params.find("");
35540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (it != red_codec.params.end()) {
35550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    red_params = it->second;
35560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    std::vector<std::string> red_pts;
35572a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    if (rtc::split(red_params, '/', &red_pts) != 2 ||
35580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        red_pts[0] != red_pts[1] ||
35592a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org        !rtc::FromString(red_pts[0], &red_pt)) {
35600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_WARNING) << "RED params " << red_params << " not supported.";
35610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
35620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
35630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (red_codec.params.empty()) {
35640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "RED params not present, using defaults";
35650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (all_codecs.size() > 1) {
35660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      red_pt = all_codecs[1].id;
35670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
35680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
35690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
35700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Try to find red_pt in |codecs|.
35710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<AudioCodec>::const_iterator codec;
35720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (codec = all_codecs.begin(); codec != all_codecs.end(); ++codec) {
35730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (codec->id == red_pt)
35740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
35750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
35760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
35770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If we find the right codec, that will be the codec we pass to
35780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // SetSendCodec, with the desired payload type.
35790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (codec != all_codecs.end() &&
35800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    engine()->FindWebRtcCodec(*codec, send_codec)) {
35810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
35820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "RED params " << red_params << " are invalid.";
35830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
35840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
35850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
35860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
35870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
35880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
35890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::EnableRtcp(int channel) {
35900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (engine()->voe()->rtp()->SetRTCPStatus(channel, true) == -1) {
3591f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    LOG_RTCERR2(SetRTCPStatus, channel, 1);
35920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
35930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
35940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO(juberti): Enable VQMon and RTCP XR reports, once we know what
35950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // what we want to do with them.
35960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // engine()->voe().EnableVQMon(voe_channel(), true);
35970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // engine()->voe().EnableRTCP_XR(voe_channel(), true);
35980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
35990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
36000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
36010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::ResetRecvCodecs(int channel) {
36020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int ncodecs = engine()->voe()->codec()->NumOfCodecs();
36030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (int i = 0; i < ncodecs; ++i) {
36040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    webrtc::CodecInst voe_codec;
36050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (engine()->voe()->codec()->GetCodec(i, voe_codec) != -1) {
36060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      voe_codec.pltype = -1;
36070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (engine()->voe()->codec()->SetRecPayloadType(
36080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          channel, voe_codec) == -1) {
36090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec));
36100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        return false;
36110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
36120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
36130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
36140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
36150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
36160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
36170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) {
36180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (playout) {
36190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_INFO) << "Starting playout for channel #" << channel;
36200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (engine()->voe()->base()->StartPlayout(channel) == -1) {
36210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_RTCERR1(StartPlayout, channel);
36220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
36230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
36240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
36250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_INFO) << "Stopping playout for channel #" << channel;
36260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    engine()->voe()->base()->StopPlayout(channel);
36270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
36280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
36290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
36300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
36310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orguint32 WebRtcVoiceMediaChannel::ParseSsrc(const void* data, size_t len,
36320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                        bool rtcp) {
36330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t ssrc_pos = (!rtcp) ? 8 : 4;
36340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 ssrc = 0;
36350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (len >= (ssrc_pos + sizeof(ssrc))) {
36362a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    ssrc = rtc::GetBE32(static_cast<const char*>(data) + ssrc_pos);
36370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
36380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ssrc;
36390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
36400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
36410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Convert VoiceEngine error code into VoiceMediaChannel::Error enum.
36420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgVoiceMediaChannel::Error
36430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    WebRtcVoiceMediaChannel::WebRtcErrorToChannelError(int err_code) {
36440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (err_code) {
36450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case 0:
36460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return ERROR_NONE;
36470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_CANNOT_START_RECORDING:
36480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_MIC_VOL_ERROR:
36490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_GET_MIC_VOL_ERROR:
36500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_CANNOT_ACCESS_MIC_VOL:
36510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return ERROR_REC_DEVICE_OPEN_FAILED;
36520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_SATURATION_WARNING:
36530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return ERROR_REC_DEVICE_SATURATION;
36540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_REC_DEVICE_REMOVED:
36550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return ERROR_REC_DEVICE_REMOVED;
36560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_RUNTIME_REC_WARNING:
36570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_RUNTIME_REC_ERROR:
36580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return ERROR_REC_RUNTIME_ERROR;
36590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_CANNOT_START_PLAYOUT:
36600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_SPEAKER_VOL_ERROR:
36610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_GET_SPEAKER_VOL_ERROR:
36620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_CANNOT_ACCESS_SPEAKER_VOL:
36630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return ERROR_PLAY_DEVICE_OPEN_FAILED;
36640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_RUNTIME_PLAY_WARNING:
36650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_RUNTIME_PLAY_ERROR:
36660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return ERROR_PLAY_RUNTIME_ERROR;
36670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case VE_TYPING_NOISE_WARNING:
36680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return ERROR_REC_TYPING_NOISE_DETECTED;
36690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    default:
36700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return VoiceMediaChannel::ERROR_OTHER;
36710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
36720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
36730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
36743ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter,
36753ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org    int channel_id, const RtpHeaderExtension* extension) {
36763ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  bool enable = false;
36772ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  int id = 0;
36782ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org  std::string uri;
36793ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  if (extension) {
36803ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org    enable = true;
36813ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org    id = extension->id;
36822ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    uri = extension->uri;
36833ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  }
36843ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  if ((engine()->voe()->rtp()->*setter)(channel_id, enable, id) != 0) {
36852ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org    LOG_RTCERR4(*setter, uri, channel_id, enable, id);
36863ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org    return false;
36873ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  }
36883ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org  return true;
36893ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org}
36903ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org
36915462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.orgbool WebRtcVoiceMediaChannel::SetupSharedBweOnChannel(int voe_channel) {
36925462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  webrtc::ViENetwork* vie_network = NULL;
36935462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  int vie_channel = -1;
36945462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  if (options_.combined_audio_video_bwe.GetWithDefaultIfUnset(false) &&
36955462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org      shared_bwe_vie_ != NULL && shared_bwe_vie_channel_ != -1) {
36965462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    vie_network = webrtc::ViENetwork::GetInterface(shared_bwe_vie_);
36975462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    vie_channel = shared_bwe_vie_channel_;
36985462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  }
36995462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  if (engine()->voe()->rtp()->SetVideoEngineBWETarget(voe_channel, vie_network,
37005462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org      vie_channel) == -1) {
37015462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    LOG_RTCERR3(SetVideoEngineBWETarget, voe_channel, vie_network, vie_channel);
37025462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    if (vie_network != NULL) {
37035462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org      // Don't fail if we're tearing down.
37045462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org      return false;
37055462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org    }
37065462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  }
37075462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org  return true;
37085462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org}
37095462dd96b8c4b0be60dd3110e70f4345c110044abuildbot@webrtc.org
37100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcSoundclipStream::Read(void *buf, int len) {
37110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t res = 0;
37120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  mem_.Read(buf, len, &res, NULL);
37131a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org  return static_cast<int>(res);
37140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
37150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
37160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcSoundclipStream::Rewind() {
37170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  mem_.Rewind();
37180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Return -1 to keep VoiceEngine from looping.
37190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return (loop_) ? 0 : -1;
37200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
37210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
37220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace cricket
37230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
37240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif  // HAVE_WEBRTC_VOICE
3725