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 410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/base64.h" 420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/byteorder.h" 430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/common.h" 440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/helpers.h" 450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/logging.h" 460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/stringencode.h" 470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/stringutils.h" 480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/audiorenderer.h" 490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/constants.h" 500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/streamparams.h" 510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/voiceprocessor.h" 520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/webrtc/webrtcvoe.h" 535528070a0c76057a000b877fc56ca4180ad2087bmallinath@webrtc.org#include "webrtc/common.h" 540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "webrtc/modules/audio_processing/include/audio_processing.h" 550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef WIN32 570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <objbase.h> // NOLINT 580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif 590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket { 610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstruct CodecPref { 630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const char* name; 640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int clockrate; 650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int channels; 660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int payload_type; 670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool is_multi_rate; 680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const CodecPref kCodecPrefs[] = { 710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "OPUS", 48000, 2, 111, true }, 720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "ISAC", 16000, 1, 103, true }, 730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "ISAC", 32000, 1, 104, true }, 740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "CELT", 32000, 1, 109, true }, 750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "CELT", 32000, 2, 110, true }, 760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "G722", 16000, 1, 9, false }, 770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "ILBC", 8000, 1, 102, false }, 780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "PCMU", 8000, 1, 0, false }, 790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "PCMA", 8000, 1, 8, false }, 800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "CN", 48000, 1, 107, false }, 810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "CN", 32000, 1, 106, false }, 820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "CN", 16000, 1, 105, false }, 830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "CN", 8000, 1, 13, false }, 840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "red", 8000, 1, 127, false }, 850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { "telephone-event", 8000, 1, 126, false }, 860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// For Linux/Mac, using the default device is done by specifying index 0 for 890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// VoE 4.0 and not -1 (which was the case for VoE 3.5). 900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// On Windows Vista and newer, Microsoft introduced the concept of "Default 920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Communications Device". This means that there are two types of default 930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// devices (old Wave Audio style default and Default Communications Device). 940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// On Windows systems which only support Wave Audio style default, uses either 960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// -1 or 0 to select the default device. 970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// On Windows systems which support both "Default Communication Device" and 990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// old Wave Audio style default, use -1 for Default Communications Device and 1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// -2 for Wave Audio style default, which is what we want to use for clips. 1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// It's not clear yet whether the -2 index is handled properly on other OSes. 1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef WIN32 1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDefaultAudioDeviceId = -1; 1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDefaultSoundclipDeviceId = -2; 1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else 1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDefaultAudioDeviceId = 0; 1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif 1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const char kIsacCodecName[] = "ISAC"; 1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const char kL16CodecName[] = "L16"; 1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Codec parameters for Opus. 1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kOpusMonoBitrate = 32000; 1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Parameter used for NACK. 1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// This value is equivalent to 5 seconds of audio data at 20 ms per packet. 1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kNackMaxPackets = 250; 1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kOpusStereoBitrate = 64000; 1187162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org// draft-spittka-payload-rtp-opus-03 1197162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org// Opus bitrate should be in the range between 6000 and 510000. 1207162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.orgstatic const int kOpusMinBitrate = 6000; 1217162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.orgstatic const int kOpusMaxBitrate = 510000; 12280303b162fe139828d0661df23e03f09126508acwu@webrtc.org// Default audio dscp value. 12380303b162fe139828d0661df23e03f09126508acwu@webrtc.org// See http://tools.ietf.org/html/rfc2474 for details. 12480303b162fe139828d0661df23e03f09126508acwu@webrtc.org// See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00 12580303b162fe139828d0661df23e03f09126508acwu@webrtc.orgstatic const talk_base::DiffServCodePoint kAudioDscpValue = talk_base::DSCP_EF; 1267162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 127ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org// Ensure we open the file in a writeable path on ChromeOS and Android. This 128ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org// workaround can be removed when it's possible to specify a filename for audio 129ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org// option based AEC dumps. 1307162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org// 1317162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org// TODO(grunell): Use a string in the options instead of hardcoding it here 1327162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org// and let the embedder choose the filename (crbug.com/264223). 1337162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org// 134ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org// NOTE(ajm): Don't use hardcoded paths on platforms not explicitly specified 135ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org// below. 136ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org#if defined(CHROMEOS) 1377162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.orgstatic const char kAecDumpByAudioOptionFilename[] = "/tmp/audio.aecdump"; 138ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.org#elif defined(ANDROID) 139ed274f89091f7acb8cacde3cae1d69cb2a19193dsergeyu@chromium.orgstatic const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump"; 1407162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org#else 1417162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.orgstatic const char kAecDumpByAudioOptionFilename[] = "audio.aecdump"; 1427162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org#endif 1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Dumps an AudioCodec in RFC 2327-ish format. 1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic std::string ToString(const AudioCodec& codec) { 1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::stringstream ss; 1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ss << codec.name << "/" << codec.clockrate << "/" << codec.channels 1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " (" << codec.id << ")"; 1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ss.str(); 1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic std::string ToString(const webrtc::CodecInst& codec) { 1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::stringstream ss; 1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ss << codec.plname << "/" << codec.plfreq << "/" << codec.channels 1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " (" << codec.pltype << ")"; 1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ss.str(); 1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic void LogMultiline(talk_base::LoggingSeverity sev, char* text) { 1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const char* delim = "\r\n"; 1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (char* tok = strtok(text, delim); tok; tok = strtok(NULL, delim)) { 1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_V(sev) << tok; 1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Severity is an integer because it comes is assumed to be from command line. 1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic int SeverityToFilter(int severity) { 1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int filter = webrtc::kTraceNone; 1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org switch (severity) { 1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case talk_base::LS_VERBOSE: 1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org filter |= webrtc::kTraceAll; 1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case talk_base::LS_INFO: 1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org filter |= (webrtc::kTraceStateInfo | webrtc::kTraceInfo); 1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case talk_base::LS_WARNING: 1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org filter |= (webrtc::kTraceTerseInfo | webrtc::kTraceWarning); 1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case talk_base::LS_ERROR: 1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org filter |= (webrtc::kTraceError | webrtc::kTraceCritical); 1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return filter; 1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic bool IsCodecMultiRate(const webrtc::CodecInst& codec) { 1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (size_t i = 0; i < ARRAY_SIZE(kCodecPrefs); ++i) { 1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (_stricmp(kCodecPrefs[i].name, codec.plname) == 0 && 1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org kCodecPrefs[i].clockrate == codec.plfreq) { 1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return kCodecPrefs[i].is_multi_rate; 1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1917587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.orgstatic bool IsTelephoneEventCodec(const std::string& name) { 1927587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org return _stricmp(name.c_str(), "telephone-event") == 0; 1937587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org} 1947587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 1957587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.orgstatic bool IsCNCodec(const std::string& name) { 1967587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org return _stricmp(name.c_str(), "CN") == 0; 1977587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org} 1987587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 1997587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.orgstatic bool IsRedCodec(const std::string& name) { 2007587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org return _stricmp(name.c_str(), "red") == 0; 2017587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org} 2027587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic bool FindCodec(const std::vector<AudioCodec>& codecs, 2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const AudioCodec& codec, 2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AudioCodec* found_codec) { 2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (std::vector<AudioCodec>::const_iterator it = codecs.begin(); 2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org it != codecs.end(); ++it) { 2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (it->Matches(codec)) { 2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (found_codec != NULL) { 2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *found_codec = *it; 2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 217cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org 2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic bool IsNackEnabled(const AudioCodec& codec) { 2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack, 2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org kParamValueEmpty)); 2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 223cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org// Gets the default set of options applied to the engine. Historically, these 224cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org// were supplied as a combination of flags from the channel manager (ec, agc, 225cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org// ns, and highpass) and the rest hardcoded in InitInternal. 226cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.orgstatic AudioOptions GetDefaultEngineOptions() { 227cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org AudioOptions options; 228cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org options.echo_cancellation.Set(true); 229cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org options.auto_gain_control.Set(true); 230cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org options.noise_suppression.Set(true); 231cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org options.highpass_filter.Set(true); 232cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org options.stereo_swapping.Set(false); 233cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org options.typing_detection.Set(true); 234cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org options.conference_mode.Set(false); 235cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org options.adjust_agc_delta.Set(0); 236cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org options.experimental_agc.Set(false); 237cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org options.experimental_aec.Set(false); 23870022fa5eb218ec690774cc4a74558699a79600asergeyu@chromium.org options.experimental_ns.Set(false); 239cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org options.aec_dump.Set(false); 24002632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org options.opus_fec.Set(false); 241cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org return options; 242cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org} 2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass WebRtcSoundclipMedia : public SoundclipMedia { 2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org public: 2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org explicit WebRtcSoundclipMedia(WebRtcVoiceEngine *engine) 2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : engine_(engine), webrtc_channel_(-1) { 2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine_->RegisterSoundclip(this); 2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org virtual ~WebRtcSoundclipMedia() { 2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine_->UnregisterSoundclip(this); 2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (webrtc_channel_ != -1) { 2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // We shouldn't have to call Disable() here. DeleteChannel() should call 2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // StopPlayout() while deleting the channel. We should fix the bug 2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // inside WebRTC and remove the Disable() call bellow. This work is 2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // tracked by bug http://b/issue?id=5382855. 2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org PlaySound(NULL, 0, 0); 2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Disable(); 2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine_->voe_sc()->base()->DeleteChannel(webrtc_channel_) 2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org == -1) { 2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR1(DeleteChannel, webrtc_channel_); 2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool Init() { 26862fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org if (!engine_->voe_sc()) { 26962fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org return false; 27062fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org } 27197fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org webrtc_channel_ = engine_->CreateSoundclipVoiceChannel(); 2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (webrtc_channel_ == -1) { 2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR0(CreateChannel); 2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool Enable() { 2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine_->voe_sc()->base()->StartPlayout(webrtc_channel_) == -1) { 2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR1(StartPlayout, webrtc_channel_); 2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool Disable() { 2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine_->voe_sc()->base()->StopPlayout(webrtc_channel_) == -1) { 2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR1(StopPlayout, webrtc_channel_); 2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org virtual bool PlaySound(const char *buf, int len, int flags) { 2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The voe file api is not available in chrome. 2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!engine_->voe_sc()->file()) { 2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Must stop playing the current sound (if any), because we are about to 3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // modify the stream. 3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine_->voe_sc()->file()->StopPlayingFileLocally(webrtc_channel_) 3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org == -1) { 3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR1(StopPlayingFileLocally, webrtc_channel_); 3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (buf) { 3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream_.reset(new WebRtcSoundclipStream(buf, len)); 3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream_->set_loop((flags & SF_LOOP) != 0); 3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream_->Rewind(); 3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Play it. 3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine_->voe_sc()->file()->StartPlayingFileLocally( 3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc_channel_, stream_.get()) == -1) { 3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR2(StartPlayingFileLocally, webrtc_channel_, stream_.get()); 3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_ERROR) << "Unable to start soundclip"; 3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream_.reset(); 3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int GetLastEngineError() const { return engine_->voe_sc()->error(); } 3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org private: 3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WebRtcVoiceEngine *engine_; 3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int webrtc_channel_; 3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::scoped_ptr<WebRtcSoundclipStream> stream_; 3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgWebRtcVoiceEngine::WebRtcVoiceEngine() 3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : voe_wrapper_(new VoEWrapper()), 3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_wrapper_sc_(new VoEWrapper()), 33762fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org voe_wrapper_sc_initialized_(false), 3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org tracing_(new VoETraceWrapper()), 3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org adm_(NULL), 3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org adm_sc_(NULL), 3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org log_filter_(SeverityToFilter(kDefaultLogSeverity)), 3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org is_dumping_aec_(false), 3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org desired_local_monitor_enable_(false), 3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org tx_processor_ssrc_(0), 3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org rx_processor_ssrc_(0) { 3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Construct(); 3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgWebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper, 3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org VoEWrapper* voe_wrapper_sc, 3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org VoETraceWrapper* tracing) 3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : voe_wrapper_(voe_wrapper), 3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_wrapper_sc_(voe_wrapper_sc), 35462fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org voe_wrapper_sc_initialized_(false), 3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org tracing_(tracing), 3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org adm_(NULL), 3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org adm_sc_(NULL), 3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org log_filter_(SeverityToFilter(kDefaultLogSeverity)), 3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org is_dumping_aec_(false), 3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org desired_local_monitor_enable_(false), 361aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org tx_processor_ssrc_(0), 362aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org rx_processor_ssrc_(0) { 363aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org Construct(); 364aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 365aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 366aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgvoid WebRtcVoiceEngine::Construct() { 367aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org SetTraceFilter(log_filter_); 368aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org initialized_ = false; 369aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine"; 370aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org SetTraceOptions(""); 371aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (tracing_->SetTraceCallback(this) == -1) { 372aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR0(SetTraceCallback); 373aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 374aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_->base()->RegisterVoiceEngineObserver(*this) == -1) { 375aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR0(RegisterVoiceEngineObserver); 376aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 377aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Clear the default agc state. 378aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org memset(&default_agc_config_, 0, sizeof(default_agc_config_)); 379aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 380aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Load our audio codec list. 381aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org ConstructCodecs(); 382aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 383aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Load our RTP Header extensions. 384aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org rtp_header_extensions_.push_back( 385aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org RtpHeaderExtension(kRtpAudioLevelHeaderExtension, 386aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org kRtpAudioLevelHeaderExtensionDefaultId)); 387aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org rtp_header_extensions_.push_back( 388aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, 389aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); 390aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org options_ = GetDefaultEngineOptions(); 391aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 392aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 393aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgstatic bool IsOpus(const AudioCodec& codec) { 394aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return (_stricmp(codec.name.c_str(), kOpusCodecName) == 0); 395aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 396aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 397aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgstatic bool IsIsac(const AudioCodec& codec) { 398aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return (_stricmp(codec.name.c_str(), kIsacCodecName) == 0); 399aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 400aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 401aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// True if params["stereo"] == "1" 402aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgstatic bool IsOpusStereoEnabled(const AudioCodec& codec) { 40302632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org int value; 40402632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org return codec.GetParam(kCodecParamStereo, &value) && value == 1; 405aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 406aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 407aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgstatic bool IsValidOpusBitrate(int bitrate) { 408aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return (bitrate >= kOpusMinBitrate && bitrate <= kOpusMaxBitrate); 409aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 410aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 411aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// Returns 0 if params[kCodecParamMaxAverageBitrate] is not defined or invalid. 412aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// Returns the value of params[kCodecParamMaxAverageBitrate] otherwise. 413aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgstatic int GetOpusBitrateFromParams(const AudioCodec& codec) { 414aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org int bitrate = 0; 415aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!codec.GetParam(kCodecParamMaxAverageBitrate, &bitrate)) { 416aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return 0; 417aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 418aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!IsValidOpusBitrate(bitrate)) { 419aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_WARNING) << "Codec parameter \"maxaveragebitrate\" has an " 420aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org << "invalid value: " << bitrate; 421aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return 0; 422aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 423aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return bitrate; 424aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 425aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 42602632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org// Return true params[kCodecParamUseInbandFec] == kParamValueTrue, false 42702632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org// otherwise. 42807617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.orgstatic bool IsOpusFecEnabled(const AudioCodec& codec) { 42902632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org int value; 43002632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org return codec.GetParam(kCodecParamUseInbandFec, &value) && value == 1; 43102632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org} 43207617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org 43302632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org// Set params[kCodecParamUseInbandFec]. Caller should make sure codec is Opus. 43402632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.orgstatic void SetOpusFec(AudioCodec *codec, bool opus_fec) { 43502632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org if (opus_fec) { 43602632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org codec->params[kCodecParamUseInbandFec] = kParamValueTrue; 43702632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org } else { 43802632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org codec->params.erase(kCodecParamUseInbandFec); 43902632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org } 44007617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org} 44107617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org 442aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgvoid WebRtcVoiceEngine::ConstructCodecs() { 443aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; 444aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org int ncodecs = voe_wrapper_->codec()->NumOfCodecs(); 445aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org for (int i = 0; i < ncodecs; ++i) { 446aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org webrtc::CodecInst voe_codec; 447aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_->codec()->GetCodec(i, voe_codec) != -1) { 448aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Skip uncompressed formats. 449aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (_stricmp(voe_codec.plname, kL16CodecName) == 0) { 450aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org continue; 451aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 452aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 453aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org const CodecPref* pref = NULL; 454aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org for (size_t j = 0; j < ARRAY_SIZE(kCodecPrefs); ++j) { 455aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (_stricmp(kCodecPrefs[j].name, voe_codec.plname) == 0 && 456aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org kCodecPrefs[j].clockrate == voe_codec.plfreq && 457aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org kCodecPrefs[j].channels == voe_codec.channels) { 458aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org pref = &kCodecPrefs[j]; 459aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org break; 460aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 461aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 462aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 463aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (pref) { 464aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Use the payload type that we've configured in our pref table; 465aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // use the offset in our pref table to determine the sort order. 466aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org AudioCodec codec(pref->payload_type, voe_codec.plname, voe_codec.plfreq, 467aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voe_codec.rate, voe_codec.channels, 468aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org ARRAY_SIZE(kCodecPrefs) - (pref - kCodecPrefs)); 469aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << ToString(codec); 470aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (IsIsac(codec)) { 471aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Indicate auto-bandwidth in signaling. 472aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org codec.bitrate = 0; 473aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 474aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (IsOpus(codec)) { 475aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Only add fmtp parameters that differ from the spec. 476aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (kPreferredMinPTime != kOpusDefaultMinPTime) { 477aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org codec.params[kCodecParamMinPTime] = 478aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org talk_base::ToString(kPreferredMinPTime); 479aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 480aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (kPreferredMaxPTime != kOpusDefaultMaxPTime) { 481aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org codec.params[kCodecParamMaxPTime] = 482aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org talk_base::ToString(kPreferredMaxPTime); 483aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 484aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // TODO(hellner): Add ptime, sprop-stereo, stereo and useinbandfec 485aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // when they can be set to values other than the default. 48602632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org SetOpusFec(&codec, false); 487aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 488aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org codecs_.push_back(codec); 489aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } else { 490aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_WARNING) << "Unexpected codec: " << ToString(voe_codec); 491aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 492aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 493aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 494aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Make sure they are in local preference order. 495aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org std::sort(codecs_.begin(), codecs_.end(), &AudioCodec::Preferable); 496aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 497aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 498aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgWebRtcVoiceEngine::~WebRtcVoiceEngine() { 499aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_VERBOSE) << "WebRtcVoiceEngine::~WebRtcVoiceEngine"; 500aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_->base()->DeRegisterVoiceEngineObserver() == -1) { 501aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR0(DeRegisterVoiceEngineObserver); 502aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 503aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (adm_) { 504aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voe_wrapper_.reset(); 505aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org adm_->Release(); 506aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org adm_ = NULL; 507aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 508aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (adm_sc_) { 509aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voe_wrapper_sc_.reset(); 510aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org adm_sc_->Release(); 511aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org adm_sc_ = NULL; 512aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 513aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 514aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Test to see if the media processor was deregistered properly 515aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org ASSERT(SignalRxMediaFrame.is_empty()); 516aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org ASSERT(SignalTxMediaFrame.is_empty()); 517aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 518aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org tracing_->SetTraceCallback(NULL); 519aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 520aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 521aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::Init(talk_base::Thread* worker_thread) { 522aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "WebRtcVoiceEngine::Init"; 523aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org bool res = InitInternal(); 524aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (res) { 525aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "WebRtcVoiceEngine::Init Done!"; 526aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } else { 527aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_ERROR) << "WebRtcVoiceEngine::Init failed"; 528aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org Terminate(); 529aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 530aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return res; 531aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 532aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 533aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::InitInternal() { 534aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Temporarily turn logging level up for the Init call 535aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org int old_filter = log_filter_; 536aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org int extended_filter = log_filter_ | SeverityToFilter(talk_base::LS_INFO); 537aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org SetTraceFilter(extended_filter); 538aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org SetTraceOptions(""); 539aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 540aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Init WebRtc VoiceEngine. 541aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_->base()->Init(adm_) == -1) { 542aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR0_EX(Init, voe_wrapper_->error()); 543aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org SetTraceFilter(old_filter); 544aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 545aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 546aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 547aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org SetTraceFilter(old_filter); 548aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org SetTraceOptions(log_options_); 549aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 550aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Log the VoiceEngine version info 551aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org char buffer[1024] = ""; 552aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voe_wrapper_->base()->GetVersion(buffer); 553aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "WebRtc VoiceEngine Version:"; 554aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LogMultiline(talk_base::LS_INFO, buffer); 555aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 556aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Save the default AGC configuration settings. This must happen before 557aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // calling SetOptions or the default will be overwritten. 558aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_->processing()->GetAgcConfig(default_agc_config_) == -1) { 559aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR0(GetAgcConfig); 560aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 561aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 562aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 563aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Set defaults for options, so that ApplyOptions applies them explicitly 564aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // when we clear option (channel) overrides. External clients can still 565aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // modify the defaults via SetOptions (on the media engine). 566aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!SetOptions(GetDefaultEngineOptions())) { 567aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 568aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 569aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 570aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Print our codec list again for the call diagnostic log 571aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; 572aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org for (std::vector<AudioCodec>::const_iterator it = codecs_.begin(); 573aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org it != codecs_.end(); ++it) { 574aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << ToString(*it); 575aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 576aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 577aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Disable the DTMF playout when a tone is sent. 578aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // PlayDtmfTone will be used if local playout is needed. 579aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_->dtmf()->SetDtmfFeedbackStatus(false) == -1) { 580aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR1(SetDtmfFeedbackStatus, false); 581aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 582aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 583aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org initialized_ = true; 584aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return true; 585aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 586aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 587aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::EnsureSoundclipEngineInit() { 588aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_sc_initialized_) { 589aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return true; 590aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 591aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Note that, if initialization fails, voe_wrapper_sc_initialized_ will still 592aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // be false, so subsequent calls to EnsureSoundclipEngineInit will 593aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // probably just fail again. That's acceptable behavior. 594aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#if defined(LINUX) && !defined(HAVE_LIBPULSE) 595aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voe_wrapper_sc_->hw()->SetAudioDeviceLayer(webrtc::kAudioLinuxAlsa); 596aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#endif 597aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 598aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Initialize the VoiceEngine instance that we'll use to play out sound clips. 599aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_sc_->base()->Init(adm_sc_) == -1) { 600aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR0_EX(Init, voe_wrapper_sc_->error()); 601aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 602aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 603aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 604aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // On Windows, tell it to use the default sound (not communication) devices. 605aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // First check whether there is a valid sound device for playback. 606aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // TODO(juberti): Clean this up when we support setting the soundclip device. 607aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#ifdef WIN32 608aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // The SetPlayoutDevice may not be implemented in the case of external ADM. 609aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // TODO(ronghuawu): We should only check the adm_sc_ here, but current 610aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // PeerConnection interface never set the adm_sc_, so need to check both 611aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // in order to determine if the external adm is used. 612aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!adm_ && !adm_sc_) { 613aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org int num_of_devices = 0; 614aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_sc_->hw()->GetNumOfPlayoutDevices(num_of_devices) != -1 && 615aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org num_of_devices > 0) { 616aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_sc_->hw()->SetPlayoutDevice(kDefaultSoundclipDeviceId) 617aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org == -1) { 618aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR1_EX(SetPlayoutDevice, kDefaultSoundclipDeviceId, 619aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voe_wrapper_sc_->error()); 620aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 621aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 622aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } else { 623aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_WARNING) << "No valid sound playout device found."; 624aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 625aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 626aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#endif 627aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voe_wrapper_sc_initialized_ = true; 628aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "Initialized WebRtc soundclip engine."; 629aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return true; 630aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 631aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 632aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgvoid WebRtcVoiceEngine::Terminate() { 633aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate"; 634aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org initialized_ = false; 635aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 636aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org StopAecDump(); 637aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 638aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_sc_) { 639aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voe_wrapper_sc_initialized_ = false; 640aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voe_wrapper_sc_->base()->Terminate(); 641aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 642aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voe_wrapper_->base()->Terminate(); 643aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org desired_local_monitor_enable_ = false; 644aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 645aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 646aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgint WebRtcVoiceEngine::GetCapabilities() { 647aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return AUDIO_SEND | AUDIO_RECV; 648aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 649aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 650aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgVoiceMediaChannel *WebRtcVoiceEngine::CreateChannel() { 651aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org WebRtcVoiceMediaChannel* ch = new WebRtcVoiceMediaChannel(this); 652aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!ch->valid()) { 653aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org delete ch; 654aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org ch = NULL; 655aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 656aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return ch; 657aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 658aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 659aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgSoundclipMedia *WebRtcVoiceEngine::CreateSoundclip() { 660aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!EnsureSoundclipEngineInit()) { 661aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_ERROR) << "Unable to create soundclip: soundclip engine failed to " 662aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org << "initialize."; 663aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return NULL; 664aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 665aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org WebRtcSoundclipMedia *soundclip = new WebRtcSoundclipMedia(this); 666aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!soundclip->Init() || !soundclip->Enable()) { 667aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org delete soundclip; 668aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return NULL; 669aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 670aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return soundclip; 671aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 672aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 673aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::SetOptions(const AudioOptions& options) { 674aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!ApplyOptions(options)) { 675aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 676aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 677aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org options_ = options; 678aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return true; 679aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 680aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 681aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::SetOptionOverrides(const AudioOptions& overrides) { 682aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "Setting option overrides: " << overrides.ToString(); 683aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!ApplyOptions(overrides)) { 684aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 685aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 686aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org option_overrides_ = overrides; 687aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return true; 688aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 689aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 690aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::ClearOptionOverrides() { 691aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "Clearing option overrides."; 692aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org AudioOptions options = options_; 693aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Only call ApplyOptions if |options_overrides_| contains overrided options. 694aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // ApplyOptions affects NS, AGC other options that is shared between 695aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // all WebRtcVoiceEngineChannels. 696aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (option_overrides_ == AudioOptions()) { 697aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return true; 698aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 699aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 700aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!ApplyOptions(options)) { 701aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 702aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 703aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org option_overrides_ = AudioOptions(); 704aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return true; 705aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 706aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 707aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// AudioOptions defaults are set in InitInternal (for options with corresponding 708aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// MediaEngineInterface flags) and in SetOptions(int) for flagless options. 709aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) { 710aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org AudioOptions options = options_in; // The options are modified below. 711aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // kEcConference is AEC with high suppression. 712aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org webrtc::EcModes ec_mode = webrtc::kEcConference; 713aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org webrtc::AecmModes aecm_mode = webrtc::kAecmSpeakerphone; 714aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog; 715aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org webrtc::NsModes ns_mode = webrtc::kNsHighSuppression; 716aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org bool aecm_comfort_noise = false; 717aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.aecm_generate_comfort_noise.Get(&aecm_comfort_noise)) { 718aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_VERBOSE) << "Comfort noise explicitly set to " 719aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org << aecm_comfort_noise << " (default is false)."; 720aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 721aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 722aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#if defined(IOS) 723aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // On iOS, VPIO provides built-in EC and AGC. 724aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org options.echo_cancellation.Set(false); 725aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org options.auto_gain_control.Set(false); 726aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#elif defined(ANDROID) 727aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org ec_mode = webrtc::kEcAecm; 728aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#endif 729aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 730aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#if defined(IOS) || defined(ANDROID) 731aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Set the AGC mode for iOS as well despite disabling it above, to avoid 732aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // unsupported configuration errors from webrtc. 733aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org agc_mode = webrtc::kAgcFixedDigital; 734aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org options.typing_detection.Set(false); 735aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org options.experimental_agc.Set(false); 736aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org options.experimental_aec.Set(false); 737aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org options.experimental_ns.Set(false); 738aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#endif 739aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 740aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "Applying audio options: " << options.ToString(); 741aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 742aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org webrtc::VoEAudioProcessing* voep = voe_wrapper_->processing(); 743aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 744aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org bool echo_cancellation; 745aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.echo_cancellation.Get(&echo_cancellation)) { 746aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voep->SetEcStatus(echo_cancellation, ec_mode) == -1) { 747aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR2(SetEcStatus, echo_cancellation, ec_mode); 748aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 749aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } else { 750aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_VERBOSE) << "Echo control set to " << echo_cancellation 751aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org << " with mode " << ec_mode; 752aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 753aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#if !defined(ANDROID) 754aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // TODO(ajm): Remove the error return on Android from webrtc. 755aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voep->SetEcMetricsStatus(echo_cancellation) == -1) { 756aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR1(SetEcMetricsStatus, echo_cancellation); 757aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 758aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 759aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#endif 760aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (ec_mode == webrtc::kEcAecm) { 761aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voep->SetAecmMode(aecm_mode, aecm_comfort_noise) != 0) { 762aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR2(SetAecmMode, aecm_mode, aecm_comfort_noise); 763aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 764aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 765aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 766aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 767aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 768aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org bool auto_gain_control; 769aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.auto_gain_control.Get(&auto_gain_control)) { 770aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voep->SetAgcStatus(auto_gain_control, agc_mode) == -1) { 771aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR2(SetAgcStatus, auto_gain_control, agc_mode); 772aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 773aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } else { 774aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_VERBOSE) << "Auto gain set to " << auto_gain_control 775aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org << " with mode " << agc_mode; 776aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 777aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 778aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 779aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.tx_agc_target_dbov.IsSet() || 780aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org options.tx_agc_digital_compression_gain.IsSet() || 781aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org options.tx_agc_limiter.IsSet()) { 782aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Override default_agc_config_. Generally, an unset option means "leave 783aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // the VoE bits alone" in this function, so we want whatever is set to be 784aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // stored as the new "default". If we didn't, then setting e.g. 785aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // tx_agc_target_dbov would reset digital compression gain and limiter 786aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // settings. 787aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Also, if we don't update default_agc_config_, then adjust_agc_delta 788aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // would be an offset from the original values, and not whatever was set 789aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // explicitly. 790aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org default_agc_config_.targetLeveldBOv = 791aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org options.tx_agc_target_dbov.GetWithDefaultIfUnset( 792aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org default_agc_config_.targetLeveldBOv); 793aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org default_agc_config_.digitalCompressionGaindB = 794aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org options.tx_agc_digital_compression_gain.GetWithDefaultIfUnset( 795aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org default_agc_config_.digitalCompressionGaindB); 796aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org default_agc_config_.limiterEnable = 797aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org options.tx_agc_limiter.GetWithDefaultIfUnset( 798aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org default_agc_config_.limiterEnable); 799aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_->processing()->SetAgcConfig(default_agc_config_) == -1) { 800aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR3(SetAgcConfig, 801aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org default_agc_config_.targetLeveldBOv, 802aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org default_agc_config_.digitalCompressionGaindB, 803aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org default_agc_config_.limiterEnable); 804aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 805aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 806aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 807aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 808aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org bool noise_suppression; 809aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.noise_suppression.Get(&noise_suppression)) { 810aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voep->SetNsStatus(noise_suppression, ns_mode) == -1) { 811aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR2(SetNsStatus, noise_suppression, ns_mode); 812aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 813aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } else { 814aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_VERBOSE) << "Noise suppression set to " << noise_suppression 815aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org << " with mode " << ns_mode; 816aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 817aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 818aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 819aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org bool experimental_ns; 820aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.experimental_ns.Get(&experimental_ns)) { 821aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org webrtc::AudioProcessing* audioproc = 822aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voe_wrapper_->base()->audio_processing(); 823aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine 824aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // returns NULL on audio_processing(). 825aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (audioproc) { 826aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (audioproc->EnableExperimentalNs(experimental_ns) == -1) { 827aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR1(EnableExperimentalNs, experimental_ns); 828aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 829aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 830aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } else { 831aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_VERBOSE) << "Experimental noise suppression set to " 832aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org << experimental_ns; 833aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 834aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 835aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 836aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org bool highpass_filter; 837aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.highpass_filter.Get(&highpass_filter)) { 838aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "High pass filter enabled? " << highpass_filter; 839aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voep->EnableHighPassFilter(highpass_filter) == -1) { 840aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR1(SetHighpassFilterStatus, highpass_filter); 841aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 842aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 843aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 844aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 845aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org bool stereo_swapping; 846aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.stereo_swapping.Get(&stereo_swapping)) { 847aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "Stereo swapping enabled? " << stereo_swapping; 848aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voep->EnableStereoChannelSwapping(stereo_swapping); 849aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voep->IsStereoChannelSwappingEnabled() != stereo_swapping) { 850aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR1(EnableStereoChannelSwapping, stereo_swapping); 851aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 852aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 853aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 854aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 855aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org bool typing_detection; 856aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.typing_detection.Get(&typing_detection)) { 857aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "Typing detection is enabled? " << typing_detection; 858aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voep->SetTypingDetectionStatus(typing_detection) == -1) { 859aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // In case of error, log the info and continue 860aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR1(SetTypingDetectionStatus, typing_detection); 861aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 862aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 863aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 864aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org int adjust_agc_delta; 865aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.adjust_agc_delta.Get(&adjust_agc_delta)) { 866aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "Adjust agc delta is " << adjust_agc_delta; 867aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!AdjustAgcLevel(adjust_agc_delta)) { 868aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 869aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 870aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 871aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 872aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org bool aec_dump; 873aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.aec_dump.Get(&aec_dump)) { 874aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "Aec dump is enabled? " << aec_dump; 875aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (aec_dump) 876aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org StartAecDump(kAecDumpByAudioOptionFilename); 877aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org else 878aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org StopAecDump(); 879aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 880aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 881aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org bool experimental_aec; 882aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.experimental_aec.Get(&experimental_aec)) { 883aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "Experimental aec is " << experimental_aec; 884aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org webrtc::AudioProcessing* audioproc = 885aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voe_wrapper_->base()->audio_processing(); 886aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine 887aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // returns NULL on audio_processing(). 888aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (audioproc) { 889aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org webrtc::Config config; 890aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org config.Set<webrtc::DelayCorrection>( 891aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org new webrtc::DelayCorrection(experimental_aec)); 892aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org audioproc->SetExtraOptions(config); 893aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 894aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 895aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 896aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org uint32 recording_sample_rate; 897aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.recording_sample_rate.Get(&recording_sample_rate)) { 898aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "Recording sample rate is " << recording_sample_rate; 899aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_->hw()->SetRecordingSampleRate(recording_sample_rate)) { 900aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR1(SetRecordingSampleRate, recording_sample_rate); 901aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 902aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 903aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 904aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org uint32 playout_sample_rate; 905aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (options.playout_sample_rate.Get(&playout_sample_rate)) { 906aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "Playout sample rate is " << playout_sample_rate; 907aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_->hw()->SetPlayoutSampleRate(playout_sample_rate)) { 908aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR1(SetPlayoutSampleRate, playout_sample_rate); 909aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 910aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 911aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 91202632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org bool opus_fec = false; 91302632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org if (options.opus_fec.Get(&opus_fec)) { 91402632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org LOG(LS_INFO) << "Opus FEC is enabled? " << opus_fec; 91502632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org for (std::vector<AudioCodec>::iterator it = codecs_.begin(); 91602632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org it != codecs_.end(); ++it) { 91702632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org if (IsOpus(*it)) 91802632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org SetOpusFec(&(*it), opus_fec); 91902632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org } 92002632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org } 92102632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org 922aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return true; 923aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 924aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 925aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::SetDelayOffset(int offset) { 926aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org voe_wrapper_->processing()->SetDelayOffsetMs(offset); 927aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_->processing()->DelayOffsetMs() != offset) { 928aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR1(SetDelayOffsetMs, offset); 929aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return false; 930aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 931aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 932aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org return true; 933aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org} 934aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 935aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgstruct ResumeEntry { 936aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org ResumeEntry(WebRtcVoiceMediaChannel *c, bool p, SendFlags s) 937aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org : channel(c), 938aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org playout(p), 939aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org send(s) { 940aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 941aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 942aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org WebRtcVoiceMediaChannel *channel; 943aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org bool playout; 944aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org SendFlags send; 945aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org}; 946aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 947aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// TODO(juberti): Refactor this so that the core logic can be used to set the 948aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org// soundclip device. At that time, reinstate the soundclip pause/resume code. 949aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.orgbool WebRtcVoiceEngine::SetDevices(const Device* in_device, 950aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org const Device* out_device) { 951aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#if !defined(IOS) 952aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org int in_id = in_device ? talk_base::FromString<int>(in_device->id) : 953aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org kDefaultAudioDeviceId; 954aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org int out_id = out_device ? talk_base::FromString<int>(out_device->id) : 955aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org kDefaultAudioDeviceId; 956aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // The device manager uses -1 as the default device, which was the case for 957aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // VoE 3.5. VoE 4.0, however, uses 0 as the default in Linux and Mac. 958aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#ifndef WIN32 959aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (-1 == in_id) { 960aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org in_id = kDefaultAudioDeviceId; 961aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 962aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (-1 == out_id) { 963aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org out_id = kDefaultAudioDeviceId; 964aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 965aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org#endif 966aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 967aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org std::string in_name = (in_id != kDefaultAudioDeviceId) ? 968aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org in_device->name : "Default device"; 969aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org std::string out_name = (out_id != kDefaultAudioDeviceId) ? 970aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org out_device->name : "Default device"; 971aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_INFO) << "Setting microphone to (id=" << in_id << ", name=" << in_name 972aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org << ") and speaker to (id=" << out_id << ", name=" << out_name 973aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org << ")"; 974aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 975aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // If we're running the local monitor, we need to stop it first. 976aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org bool ret = true; 977aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!PauseLocalMonitor()) { 978aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_WARNING) << "Failed to pause local monitor"; 979aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org ret = false; 980aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 981aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 982aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Must also pause all audio playback and capture. 983aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org for (ChannelList::const_iterator i = channels_.begin(); 984aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org i != channels_.end(); ++i) { 985aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org WebRtcVoiceMediaChannel *channel = *i; 986aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!channel->PausePlayout()) { 987aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_WARNING) << "Failed to pause playout"; 988aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org ret = false; 989aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 990aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!channel->PauseSend()) { 991aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG(LS_WARNING) << "Failed to pause send"; 992aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org ret = false; 993aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 994aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 995aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org 996aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org // Find the recording device id in VoiceEngine and set recording device. 997aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (!FindWebRtcAudioDeviceId(true, in_name, in_id, &in_id)) { 998aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org ret = false; 999aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 1000aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (ret) { 1001aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org if (voe_wrapper_->hw()->SetRecordingDevice(in_id) == -1) { 1002aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org LOG_RTCERR2(SetRecordingDevice, in_name, in_id); 1003aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org ret = false; 1004aa0311d805f9d06dd334d9750e42824e93ba707abuildbot@webrtc.org } 10050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Find the playout device id in VoiceEngine and set playout device. 10080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!FindWebRtcAudioDeviceId(false, out_name, out_id, &out_id)) { 10090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Failed to find VoiceEngine device id for " << out_name; 10100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ret = false; 10110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ret) { 10130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (voe_wrapper_->hw()->SetPlayoutDevice(out_id) == -1) { 101497fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org LOG_RTCERR2(SetPlayoutDevice, out_name, out_id); 10150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ret = false; 10160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Resume all audio playback and capture. 10200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (ChannelList::const_iterator i = channels_.begin(); 10210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org i != channels_.end(); ++i) { 10220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WebRtcVoiceMediaChannel *channel = *i; 10230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!channel->ResumePlayout()) { 10240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Failed to resume playout"; 10250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ret = false; 10260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!channel->ResumeSend()) { 10280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Failed to resume send"; 10290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ret = false; 10300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Resume local monitor. 10340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ResumeLocalMonitor()) { 10350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Failed to resume local monitor"; 10360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ret = false; 10370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ret) { 10400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Set microphone to (id=" << in_id <<" name=" << in_name 10410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << ") and speaker to (id="<< out_id << " name=" << out_name 10420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << ")"; 10430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ret; 10460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else 10470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 1048d1f631d5ec5c25dd0a63ed70d0ffa66037d8aa6awu@webrtc.org#endif // !IOS 10490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 10500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::FindWebRtcAudioDeviceId( 10520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool is_input, const std::string& dev_name, int dev_id, int* rtc_id) { 10530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // In Linux, VoiceEngine uses the same device dev_id as the device manager. 1054d1f631d5ec5c25dd0a63ed70d0ffa66037d8aa6awu@webrtc.org#if defined(LINUX) || defined(ANDROID) 10550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *rtc_id = dev_id; 10560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 10570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else 10580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // In Windows and Mac, we need to find the VoiceEngine device id by name 10590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // unless the input dev_id is the default device id. 10600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (kDefaultAudioDeviceId == dev_id) { 10610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *rtc_id = dev_id; 10620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 10630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Get the number of VoiceEngine audio devices. 10660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int count = 0; 10670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (is_input) { 10680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (-1 == voe_wrapper_->hw()->GetNumOfRecordingDevices(count)) { 10690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR0(GetNumOfRecordingDevices); 10700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 10710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 10730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (-1 == voe_wrapper_->hw()->GetNumOfPlayoutDevices(count)) { 10740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR0(GetNumOfPlayoutDevices); 10750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 10760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (int i = 0; i < count; ++i) { 10800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org char name[128]; 10810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org char guid[128]; 10820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (is_input) { 10830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_wrapper_->hw()->GetRecordingDeviceName(i, name, guid); 10840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_VERBOSE) << "VoiceEngine microphone " << i << ": " << name; 10850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 10860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_wrapper_->hw()->GetPlayoutDeviceName(i, name, guid); 10870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_VERBOSE) << "VoiceEngine speaker " << i << ": " << name; 10880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string webrtc_name(name); 10910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (dev_name.compare(0, webrtc_name.size(), webrtc_name) == 0) { 10920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *rtc_id = i; 10930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 10940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "VoiceEngine cannot find device: " << dev_name; 10970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 10980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif 10990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::GetOutputVolume(int* level) { 11020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org unsigned int ulevel; 11030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (voe_wrapper_->volume()->GetSpeakerVolume(ulevel) == -1) { 11040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR1(GetSpeakerVolume, level); 11050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 11060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *level = ulevel; 11080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 11090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::SetOutputVolume(int level) { 11120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(level >= 0 && level <= 255); 11130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (voe_wrapper_->volume()->SetSpeakerVolume(level) == -1) { 11140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR1(SetSpeakerVolume, level); 11150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 11160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 11180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceEngine::GetInputLevel() { 11210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org unsigned int ulevel; 11220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (voe_wrapper_->volume()->GetSpeechInputLevel(ulevel) != -1) ? 11230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static_cast<int>(ulevel) : -1; 11240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::SetLocalMonitor(bool enable) { 11270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org desired_local_monitor_enable_ = enable; 11280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ChangeLocalMonitor(desired_local_monitor_enable_); 11290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::ChangeLocalMonitor(bool enable) { 11320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The voe file api is not available in chrome. 11330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!voe_wrapper_->file()) { 11340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 11350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (enable && !monitor_) { 11370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org monitor_.reset(new WebRtcMonitorStream); 11380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (voe_wrapper_->file()->StartRecordingMicrophone(monitor_.get()) == -1) { 11390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR1(StartRecordingMicrophone, monitor_.get()); 11400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Must call Stop() because there are some cases where Start will report 11410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // failure but still change the state, and if we leave VE in the on state 11420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // then it could crash later when trying to invoke methods on our monitor. 11430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_wrapper_->file()->StopRecordingMicrophone(); 11440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org monitor_.reset(); 11450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 11460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (!enable && monitor_) { 11480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_wrapper_->file()->StopRecordingMicrophone(); 11490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org monitor_.reset(); 11500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 11520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::PauseLocalMonitor() { 11550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ChangeLocalMonitor(false); 11560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::ResumeLocalMonitor() { 11590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ChangeLocalMonitor(desired_local_monitor_enable_); 11600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst std::vector<AudioCodec>& WebRtcVoiceEngine::codecs() { 11630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return codecs_; 11640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::FindCodec(const AudioCodec& in) { 11670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return FindWebRtcCodec(in, NULL); 11680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Get the VoiceEngine codec that matches |in|, with the supplied settings. 11710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::FindWebRtcCodec(const AudioCodec& in, 11720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::CodecInst* out) { 11730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int ncodecs = voe_wrapper_->codec()->NumOfCodecs(); 11740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (int i = 0; i < ncodecs; ++i) { 11750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::CodecInst voe_codec; 11760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (voe_wrapper_->codec()->GetCodec(i, voe_codec) != -1) { 11770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AudioCodec codec(voe_codec.pltype, voe_codec.plname, voe_codec.plfreq, 11780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_codec.rate, voe_codec.channels, 0); 11790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool multi_rate = IsCodecMultiRate(voe_codec); 11800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Allow arbitrary rates for ISAC to be specified. 11810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (multi_rate) { 11820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Set codec.bitrate to 0 so the check for codec.Matches() passes. 11830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org codec.bitrate = 0; 11840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (codec.Matches(in)) { 11860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (out) { 11870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Fixup the payload type. 11880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_codec.pltype = in.id; 11890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Set bitrate if specified. 11910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (multi_rate && in.bitrate != 0) { 11920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_codec.rate = in.bitrate; 11930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Apply codec-specific settings. 11960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (IsIsac(codec)) { 11970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If ISAC and an explicit bitrate is not specified, 11980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // enable auto bandwidth adjustment. 11990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_codec.rate = (in.bitrate > 0) ? in.bitrate : -1; 12000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 12010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *out = voe_codec; 12020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 12030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 12040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 12050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 12060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 12070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 12080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 12090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst std::vector<RtpHeaderExtension>& 12100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgWebRtcVoiceEngine::rtp_header_extensions() const { 12110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return rtp_header_extensions_; 12120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 12130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 12140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::SetLogging(int min_sev, const char* filter) { 12150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // if min_sev == -1, we keep the current log level. 12160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (min_sev >= 0) { 12170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetTraceFilter(SeverityToFilter(min_sev)); 12180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 12190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org log_options_ = filter; 12200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetTraceOptions(initialized_ ? log_options_ : ""); 12210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 12220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 12230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceEngine::GetLastEngineError() { 12240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return voe_wrapper_->error(); 12250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 12260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 12270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::SetTraceFilter(int filter) { 12280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org log_filter_ = filter; 12290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org tracing_->SetTraceFilter(filter); 12300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 12310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 12320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// We suppport three different logging settings for VoiceEngine: 12330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 1. Observer callback that goes into talk diagnostic logfile. 12340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Use --logfile and --loglevel 12350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 12360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 2. Encrypted VoiceEngine log for debugging VoiceEngine. 12370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Use --voice_loglevel --voice_logfilter "tracefile file_name" 12380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 12390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 3. EC log and dump for debugging QualityEngine. 12400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Use --voice_loglevel --voice_logfilter "recordEC file_name" 12410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 12420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// For more details see: "https://sites.google.com/a/google.com/wavelet/Home/ 12430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Magic-Flute--RTC-Engine-/Magic-Flute-Command-Line-Parameters" 12440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::SetTraceOptions(const std::string& options) { 12450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Set encrypted trace file. 12460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<std::string> opts; 12470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::tokenize(options, ' ', '"', '"', &opts); 12480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<std::string>::iterator tracefile = 12490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::find(opts.begin(), opts.end(), "tracefile"); 12500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (tracefile != opts.end() && ++tracefile != opts.end()) { 12510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Write encrypted debug output (at same loglevel) to file 12520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // EncryptedTraceFile no longer supported. 12530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (tracing_->SetTraceFile(tracefile->c_str()) == -1) { 12540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR1(SetTraceFile, *tracefile); 12550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 12560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 12570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 12585c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org // Allow trace options to override the trace filter. We default 12595c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org // it to log_filter_ (as a translation of libjingle log levels) 12605c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org // elsewhere, but this allows clients to explicitly set webrtc 12615c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org // log levels. 12625c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org std::vector<std::string>::iterator tracefilter = 12635c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org std::find(opts.begin(), opts.end(), "tracefilter"); 12645c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org if (tracefilter != opts.end() && ++tracefilter != opts.end()) { 12655c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org if (!tracing_->SetTraceFilter(talk_base::FromString<int>(*tracefilter))) { 12665c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org LOG_RTCERR1(SetTraceFilter, *tracefilter); 12675c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org } 12685c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org } 12695c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org 12700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Set AEC dump file 12710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<std::string>::iterator recordEC = 12720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::find(opts.begin(), opts.end(), "recordEC"); 12730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (recordEC != opts.end()) { 12740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ++recordEC; 12750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (recordEC != opts.end()) 12760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org StartAecDump(recordEC->c_str()); 12770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org else 12780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org StopAecDump(); 12790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 12800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 12810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 12820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Ignore spammy trace messages, mostly from the stats API when we haven't 12830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// gotten RTCP info yet from the remote side. 12840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::ShouldIgnoreTrace(const std::string& trace) { 12850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static const char* kTracesToIgnore[] = { 12860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "\tfailed to GetReportBlockInformation", 12870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "GetRecCodec() failed to get received codec", 12880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "GetReceivedRtcpStatistics: Could not get received RTP statistics", 12890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "GetRemoteRTCPData() failed to measure statistics due to lack of received RTP and/or RTCP packets", // NOLINT 12900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "GetRemoteRTCPData() failed to retrieve sender info for remote side", 12910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "GetRTPStatistics() failed to measure RTT since no RTP packets have been received yet", // NOLINT 12920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "GetRTPStatistics() failed to read RTP statistics from the RTP/RTCP module", 12930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "GetRTPStatistics() failed to retrieve RTT from the RTP/RTCP module", 12940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "SenderInfoReceived No received SR", 12950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "StatisticsRTP() no statistics available", 12960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "TransmitMixer::TypingDetection() VE_TYPING_NOISE_WARNING message has been posted", // NOLINT 12970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "TransmitMixer::TypingDetection() pending noise-saturation warning exists", // NOLINT 12980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "GetRecPayloadType() failed to retrieve RX payload type (error=10026)", // NOLINT 12990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "StopPlayingFileAsMicrophone() isnot playing (error=8088)", 13000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org NULL 13010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org }; 13020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (const char* const* p = kTracesToIgnore; *p; ++p) { 13030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (trace.find(*p) != std::string::npos) { 13040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 13050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 13060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 13070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 13080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 13090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 13100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace, 13110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int length) { 13120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::LoggingSeverity sev = talk_base::LS_VERBOSE; 13130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (level == webrtc::kTraceError || level == webrtc::kTraceCritical) 13140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sev = talk_base::LS_ERROR; 13150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org else if (level == webrtc::kTraceWarning) 13160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sev = talk_base::LS_WARNING; 13170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo) 13180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sev = talk_base::LS_INFO; 13190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org else if (level == webrtc::kTraceTerseInfo) 13200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sev = talk_base::LS_INFO; 13210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 13220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Skip past boilerplate prefix text 13230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (length < 72) { 13240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string msg(trace, length); 13250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_ERROR) << "Malformed webrtc log message: "; 13260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_V(sev) << msg; 13270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 13280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string msg(trace + 71, length - 72); 13290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ShouldIgnoreTrace(msg)) { 13300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_V(sev) << "webrtc: " << msg; 13310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 13320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 13330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 13340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 13350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::CallbackOnError(int channel_num, int err_code) { 13360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::CritScope lock(&channels_cs_); 13370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WebRtcVoiceMediaChannel* channel = NULL; 13380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 ssrc = 0; 13390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "VoiceEngine error " << err_code << " reported on channel " 13400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << channel_num << "."; 13410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (FindChannelAndSsrc(channel_num, &channel, &ssrc)) { 13420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(channel != NULL); 13430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel->OnError(ssrc, err_code); 13440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 13450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_ERROR) << "VoiceEngine channel " << channel_num 13460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " could not be found in channel list when error reported."; 13470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 13480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 13490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 13500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::FindChannelAndSsrc( 13510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int channel_num, WebRtcVoiceMediaChannel** channel, uint32* ssrc) const { 13520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(channel != NULL && ssrc != NULL); 13530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 13540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *channel = NULL; 13550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *ssrc = 0; 13560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Find corresponding channel and ssrc 13570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (ChannelList::const_iterator it = channels_.begin(); 13580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org it != channels_.end(); ++it) { 13590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(*it != NULL); 13600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if ((*it)->FindSsrc(channel_num, ssrc)) { 13610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *channel = *it; 13620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 13630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 13640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 13650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 13660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 13670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 13680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 13690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// This method will search through the WebRtcVoiceMediaChannels and 13700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// obtain the voice engine's channel number. 13710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::FindChannelNumFromSsrc( 13720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 ssrc, MediaProcessorDirection direction, int* channel_num) { 13730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(channel_num != NULL); 13740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(direction == MPD_RX || direction == MPD_TX); 13750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 13760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *channel_num = -1; 13770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Find corresponding channel for ssrc. 13780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (ChannelList::const_iterator it = channels_.begin(); 13790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org it != channels_.end(); ++it) { 13800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(*it != NULL); 13810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (direction & MPD_RX) { 13820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *channel_num = (*it)->GetReceiveChannelNum(ssrc); 13830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 13840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (*channel_num == -1 && (direction & MPD_TX)) { 13850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *channel_num = (*it)->GetSendChannelNum(ssrc); 13860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 13870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (*channel_num != -1) { 13880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 13890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 13900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 13910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "FindChannelFromSsrc. No Channel Found for Ssrc: " << ssrc; 13920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 13930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 13940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 13950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel *channel) { 13960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::CritScope lock(&channels_cs_); 13970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channels_.push_back(channel); 13980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 13990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 14000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel *channel) { 14010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::CritScope lock(&channels_cs_); 14020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ChannelList::iterator i = std::find(channels_.begin(), 14030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channels_.end(), 14040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel); 14050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (i != channels_.end()) { 14060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channels_.erase(i); 14070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 14080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 14090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 14100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::RegisterSoundclip(WebRtcSoundclipMedia *soundclip) { 14110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org soundclips_.push_back(soundclip); 14120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 14130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 14140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::UnregisterSoundclip(WebRtcSoundclipMedia *soundclip) { 14150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SoundclipList::iterator i = std::find(soundclips_.begin(), 14160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org soundclips_.end(), 14170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org soundclip); 14180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (i != soundclips_.end()) { 14190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org soundclips_.erase(i); 14200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 14210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 14220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 14230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Adjusts the default AGC target level by the specified delta. 14240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// NB: If we start messing with other config fields, we'll want 14250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// to save the current webrtc::AgcConfig as well. 14260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::AdjustAgcLevel(int delta) { 14270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::AgcConfig config = default_agc_config_; 14280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org config.targetLeveldBOv -= delta; 14290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 14300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Adjusting AGC level from default -" 14310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << default_agc_config_.targetLeveldBOv << "dB to -" 14320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << config.targetLeveldBOv << "dB"; 14330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 14340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (voe_wrapper_->processing()->SetAgcConfig(config) == -1) { 14350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR1(SetAgcConfig, config.targetLeveldBOv); 14360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 14370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 14380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 14390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 14400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 14410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::SetAudioDeviceModule(webrtc::AudioDeviceModule* adm, 14420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::AudioDeviceModule* adm_sc) { 14430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (initialized_) { 14440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "SetAudioDeviceModule can not be called after Init."; 14450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 14460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 14470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (adm_) { 14480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org adm_->Release(); 14490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org adm_ = NULL; 14500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 14510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (adm) { 14520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org adm_ = adm; 14530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org adm_->AddRef(); 14540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 14550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 14560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (adm_sc_) { 14570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org adm_sc_->Release(); 14580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org adm_sc_ = NULL; 14590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 14600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (adm_sc) { 14610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org adm_sc_ = adm_sc; 14620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org adm_sc_->AddRef(); 14630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 14640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 14650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 14660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 14671b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.orgbool WebRtcVoiceEngine::StartAecDump(talk_base::PlatformFile file) { 14681b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org FILE* aec_dump_file_stream = talk_base::FdopenPlatformFileForWriting(file); 14691b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org if (!aec_dump_file_stream) { 14701b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org LOG(LS_ERROR) << "Could not open AEC dump file stream."; 14711b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org if (!talk_base::ClosePlatformFile(file)) 14721b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org LOG(LS_WARNING) << "Could not close file."; 14731b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org return false; 14741b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org } 1475f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org StopAecDump(); 14761b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org if (voe_wrapper_->processing()->StartDebugRecording(aec_dump_file_stream) != 1477f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org webrtc::AudioProcessing::kNoError) { 14781b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org LOG_RTCERR0(StartDebugRecording); 14791b5713169ff3f21791214c4500e5d775048c3ba9wu@webrtc.org fclose(aec_dump_file_stream); 1480f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org return false; 1481f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org } 1482f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org is_dumping_aec_ = true; 1483f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org return true; 1484f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org} 1485f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org 14860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::RegisterProcessor( 14870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 ssrc, 14880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org VoiceProcessor* voice_processor, 14890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaProcessorDirection direction) { 14900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool register_with_webrtc = false; 14910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int channel_id = -1; 14920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool success = false; 14930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32* processor_ssrc = NULL; 14940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool found_channel = FindChannelNumFromSsrc(ssrc, direction, &channel_id); 14950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (voice_processor == NULL || !found_channel) { 14960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Media Processing Registration Failed. ssrc: " << ssrc 14970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " foundChannel: " << found_channel; 14980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 14990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 15000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 15010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::ProcessingTypes processing_type; 15020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { 15030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::CritScope cs(&signal_media_critical_); 15040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (direction == MPD_RX) { 15050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org processing_type = webrtc::kPlaybackAllChannelsMixed; 15060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (SignalRxMediaFrame.is_empty()) { 15070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org register_with_webrtc = true; 15080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org processor_ssrc = &rx_processor_ssrc_; 15090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 15100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SignalRxMediaFrame.connect(voice_processor, 15110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org &VoiceProcessor::OnFrame); 15120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 15130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org processing_type = webrtc::kRecordingPerChannel; 15140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (SignalTxMediaFrame.is_empty()) { 15150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org register_with_webrtc = true; 15160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org processor_ssrc = &tx_processor_ssrc_; 15170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 15180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SignalTxMediaFrame.connect(voice_processor, 15190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org &VoiceProcessor::OnFrame); 15200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 15210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 15220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (register_with_webrtc) { 15230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(janahan): when registering consider instantiating a 15240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // a VoeMediaProcess object and not make the engine extend the interface. 15250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (voe()->media() && voe()->media()-> 15260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org RegisterExternalMediaProcessing(channel_id, 15270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org processing_type, 15280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *this) != -1) { 15290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Media Processing Registration Succeeded. channel:" 15300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << channel_id; 15310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *processor_ssrc = ssrc; 15320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org success = true; 15330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 15340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR2(RegisterExternalMediaProcessing, 15350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel_id, 15360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org processing_type); 15370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org success = false; 15380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 15390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 15400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If we don't have to register with the engine, we just needed to 15410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // connect a new processor, set success to true; 15420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org success = true; 15430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 15440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return success; 15450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 15460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 15470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::UnregisterProcessorChannel( 15480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaProcessorDirection channel_direction, 15490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 ssrc, 15500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org VoiceProcessor* voice_processor, 15510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaProcessorDirection processor_direction) { 15520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool success = true; 15530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org FrameSignal* signal; 15540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::ProcessingTypes processing_type; 15550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32* processor_ssrc = NULL; 15560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (channel_direction == MPD_RX) { 15570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org signal = &SignalRxMediaFrame; 15580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org processing_type = webrtc::kPlaybackAllChannelsMixed; 15590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org processor_ssrc = &rx_processor_ssrc_; 15600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 15610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org signal = &SignalTxMediaFrame; 15620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org processing_type = webrtc::kRecordingPerChannel; 15630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org processor_ssrc = &tx_processor_ssrc_; 15640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 15650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 15660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int deregister_id = -1; 15670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org { 15680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::CritScope cs(&signal_media_critical_); 15690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if ((processor_direction & channel_direction) != 0 && !signal->is_empty()) { 15700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org signal->disconnect(voice_processor); 15710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int channel_id = -1; 15720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool found_channel = FindChannelNumFromSsrc(ssrc, 15730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel_direction, 15740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org &channel_id); 15750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (signal->is_empty() && found_channel) { 15760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org deregister_id = channel_id; 15770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 15780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 15790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 15800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (deregister_id != -1) { 15810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (voe()->media() && 15820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe()->media()->DeRegisterExternalMediaProcessing(deregister_id, 15830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org processing_type) != -1) { 15840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *processor_ssrc = 0; 15850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Media Processing DeRegistration Succeeded. channel:" 15860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << deregister_id; 15870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 15880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR2(DeRegisterExternalMediaProcessing, 15890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org deregister_id, 15900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org processing_type); 15910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org success = false; 15920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 15930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 15940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return success; 15950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 15960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 15970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceEngine::UnregisterProcessor( 15980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 ssrc, 15990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org VoiceProcessor* voice_processor, 16000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaProcessorDirection direction) { 16010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool success = true; 16020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (voice_processor == NULL) { 16030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Media Processing Deregistration Failed. ssrc: " 16040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << ssrc; 16050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 16060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 16070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!UnregisterProcessorChannel(MPD_RX, ssrc, voice_processor, direction)) { 16080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org success = false; 16090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 16100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!UnregisterProcessorChannel(MPD_TX, ssrc, voice_processor, direction)) { 16110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org success = false; 16120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 16130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return success; 16140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 16150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 16160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Implementing method from WebRtc VoEMediaProcess interface 16170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Do not lock mux_channel_cs_ in this callback. 16180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::Process(int channel, 16190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::ProcessingTypes type, 16200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int16_t audio10ms[], 16210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int length, 16220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int sampling_freq, 16230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool is_stereo) { 16240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::CritScope cs(&signal_media_critical_); 16250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AudioFrame frame(audio10ms, length, sampling_freq, is_stereo); 16260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (type == webrtc::kPlaybackAllChannelsMixed) { 16270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SignalRxMediaFrame(rx_processor_ssrc_, MPD_RX, &frame); 16280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (type == webrtc::kRecordingPerChannel) { 16290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SignalTxMediaFrame(tx_processor_ssrc_, MPD_TX, &frame); 16300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 16310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Media Processing invoked unexpectedly." 16320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " channel: " << channel << " type: " << type 16330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " tx_ssrc: " << tx_processor_ssrc_ 16340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " rx_ssrc: " << rx_processor_ssrc_; 16350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 16360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 16370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 16380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::StartAecDump(const std::string& filename) { 16390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!is_dumping_aec_) { 16400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Start dumping AEC when we are not dumping. 16410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (voe_wrapper_->processing()->StartDebugRecording( 16420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org filename.c_str()) != webrtc::AudioProcessing::kNoError) { 1643f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org LOG_RTCERR1(StartDebugRecording, filename.c_str()); 16440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 16450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org is_dumping_aec_ = true; 16460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 16470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 16480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 16490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 16500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceEngine::StopAecDump() { 16510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (is_dumping_aec_) { 16520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Stop dumping AEC when we are dumping. 16530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (voe_wrapper_->processing()->StopDebugRecording() != 16540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::AudioProcessing::kNoError) { 16550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR0(StopDebugRecording); 16560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 16570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org is_dumping_aec_ = false; 16580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 16590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 16600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 166197fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.orgint WebRtcVoiceEngine::CreateVoiceChannel(VoEWrapper* voice_engine_wrapper) { 166297fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org return voice_engine_wrapper->base()->CreateChannel(voe_config_); 166397fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org} 166497fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org 166597fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.orgint WebRtcVoiceEngine::CreateMediaVoiceChannel() { 166697fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org return CreateVoiceChannel(voe_wrapper_.get()); 166797fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org} 166897fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org 166997fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.orgint WebRtcVoiceEngine::CreateSoundclipVoiceChannel() { 167097fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org return CreateVoiceChannel(voe_wrapper_sc_.get()); 167197fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org} 167297fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org 1673b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.orgclass WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer 1674b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org : public AudioRenderer::Sink { 1675b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org public: 1676b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org WebRtcVoiceChannelRenderer(int ch, 1677b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org webrtc::AudioTransport* voe_audio_transport) 1678b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org : channel_(ch), 1679b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org voe_audio_transport_(voe_audio_transport), 1680b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org renderer_(NULL) { 1681b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org } 1682b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org virtual ~WebRtcVoiceChannelRenderer() { 1683b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org Stop(); 1684b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org } 1685b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org 1686b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // Starts the rendering by setting a sink to the renderer to get data 1687b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // callback. 1688e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org // This method is called on the libjingle worker thread. 1689b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // TODO(xians): Make sure Start() is called only once. 1690b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org void Start(AudioRenderer* renderer) { 1691e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org talk_base::CritScope lock(&lock_); 1692b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org ASSERT(renderer != NULL); 1693e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org if (renderer_ != NULL) { 1694b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org ASSERT(renderer_ == renderer); 1695b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org return; 1696b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org } 1697b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org 1698b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // TODO(xians): Remove AddChannel() call after Chrome turns on APM 1699b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // in getUserMedia by default. 1700b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org renderer->AddChannel(channel_); 1701b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org renderer->SetSink(this); 1702b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org renderer_ = renderer; 1703b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org } 1704b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org 1705b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // Stops rendering by setting the sink of the renderer to NULL. No data 1706b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // callback will be received after this method. 1707e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org // This method is called on the libjingle worker thread. 1708b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org void Stop() { 1709e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org talk_base::CritScope lock(&lock_); 1710e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org if (renderer_ == NULL) 1711b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org return; 1712b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org 1713b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org renderer_->RemoveChannel(channel_); 1714b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org renderer_->SetSink(NULL); 1715b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org renderer_ = NULL; 1716b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org } 1717b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org 1718b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // AudioRenderer::Sink implementation. 1719e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org // This method is called on the audio thread. 1720b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org virtual void OnData(const void* audio_data, 1721b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org int bits_per_sample, 1722b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org int sample_rate, 1723b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org int number_of_channels, 1724b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org int number_of_frames) OVERRIDE { 1725e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org voe_audio_transport_->OnData(channel_, 1726e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org audio_data, 1727e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org bits_per_sample, 1728e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org sample_rate, 1729e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org number_of_channels, 1730e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org number_of_frames); 1731e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org } 1732e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org 1733e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org // Callback from the |renderer_| when it is going away. In case Start() has 1734e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org // never been called, this callback won't be triggered. 1735e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org virtual void OnClose() OVERRIDE { 1736e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org talk_base::CritScope lock(&lock_); 1737e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org // Set |renderer_| to NULL to make sure no more callback will get into 1738e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org // the renderer. 1739e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org renderer_ = NULL; 1740b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org } 1741b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org 1742b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // Accessor to the VoE channel ID. 1743b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org int channel() const { return channel_; } 1744b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org 1745b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org private: 1746b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org const int channel_; 1747b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org webrtc::AudioTransport* const voe_audio_transport_; 1748b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org 1749b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler. 1750b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // PeerConnection will make sure invalidating the pointer before the object 1751b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // goes away. 1752b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org AudioRenderer* renderer_; 1753e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org 1754e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org // Protects |renderer_| in Start(), Stop() and OnClose(). 1755e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org talk_base::CriticalSection lock_; 17567162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org}; 17577162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 17580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// WebRtcVoiceMediaChannel 17590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgWebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine *engine) 17600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : WebRtcMediaChannel<VoiceMediaChannel, WebRtcVoiceEngine>( 17610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine, 176297fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org engine->CreateMediaVoiceChannel()), 1763cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org send_bw_setting_(false), 1764cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org send_bw_bps_(0), 17650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org options_(), 17660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org dtmf_allowed_(false), 17670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org desired_playout_(false), 17680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org nack_enabled_(false), 17690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org playout_(false), 17704ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org typing_noise_detected_(false), 17710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org desired_send_(SEND_NOTHING), 17720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org send_(SEND_NOTHING), 17730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org default_receive_ssrc_(0) { 17740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine->RegisterChannel(this); 17750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel " 17760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << voe_channel(); 17770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1778f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org ConfigureSendChannel(voe_channel()); 17790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 17800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 17810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgWebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() { 17820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel " 17830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << voe_channel(); 17840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1785f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Remove any remaining send streams, the default channel will be deleted 1786f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // later. 1787f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org while (!send_channels_.empty()) 1788f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org RemoveSendStream(send_channels_.begin()->first); 17890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 17900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Unregister ourselves from the engine. 17910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine()->UnregisterChannel(this); 17920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Remove any remaining streams. 17937162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org while (!receive_channels_.empty()) { 17947162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org RemoveRecvStream(receive_channels_.begin()->first); 17950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 17960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1797f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Delete the default channel. 1798f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org DeleteChannel(voe_channel()); 17990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 18000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 18010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { 18020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Setting voice channel options: " 18030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << options.ToString(); 18040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 180580303b162fe139828d0661df23e03f09126508acwu@webrtc.org // Check if DSCP value is changed from previous. 180680303b162fe139828d0661df23e03f09126508acwu@webrtc.org bool dscp_option_changed = (options_.dscp != options.dscp); 180780303b162fe139828d0661df23e03f09126508acwu@webrtc.org 1808f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // TODO(xians): Add support to set different options for different send 1809f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // streams after we support multiple APMs. 1810f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 18110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // We retain all of the existing options, and apply the given ones 18120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // on top. This means there is no way to "clear" options such that 18130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // they go back to the engine default. 18140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org options_.SetAll(options); 18150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 18160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (send_ != SEND_NOTHING) { 18170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!engine()->SetOptionOverrides(options_)) { 18180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << 18190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "Failed to engine SetOptionOverrides during channel SetOptions."; 18200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 18210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 18220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 18230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Will be interpreted when appropriate. 18240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 18250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 18265c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org // Receiver-side auto gain control happens per channel, so set it here from 18275c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org // options. Note that, like conference mode, setting it on the engine won't 18285c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org // have the desired effect, since voice channels don't inherit options from 18295c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org // the media engine when those options are applied per-channel. 18305c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org bool rx_auto_gain_control; 18315c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org if (options.rx_auto_gain_control.Get(&rx_auto_gain_control)) { 18325c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org if (engine()->voe()->processing()->SetRxAgcStatus( 18335c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org voe_channel(), rx_auto_gain_control, 18345c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org webrtc::kAgcFixedDigital) == -1) { 18355c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org LOG_RTCERR1(SetRxAgcStatus, rx_auto_gain_control); 18365c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org return false; 18375c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org } else { 18385c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org LOG(LS_VERBOSE) << "Rx auto gain set to " << rx_auto_gain_control 18395c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org << " with mode " << webrtc::kAgcFixedDigital; 18405c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org } 18415c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org } 18425c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org if (options.rx_agc_target_dbov.IsSet() || 18435c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org options.rx_agc_digital_compression_gain.IsSet() || 18445c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org options.rx_agc_limiter.IsSet()) { 18455c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org webrtc::AgcConfig config; 18465c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org // If only some of the options are being overridden, get the current 18475c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org // settings for the channel and bail if they aren't available. 18485c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org if (!options.rx_agc_target_dbov.IsSet() || 18495c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org !options.rx_agc_digital_compression_gain.IsSet() || 18505c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org !options.rx_agc_limiter.IsSet()) { 18515c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org if (engine()->voe()->processing()->GetRxAgcConfig( 18525c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org voe_channel(), config) != 0) { 18535c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org LOG(LS_ERROR) << "Failed to get default rx agc configuration for " 18545c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org << "channel " << voe_channel() << ". Since not all rx " 18555c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org << "agc options are specified, unable to safely set rx " 18565c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org << "agc options."; 18575c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org return false; 18585c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org } 18595c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org } 18605c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org config.targetLeveldBOv = 18615c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org options.rx_agc_target_dbov.GetWithDefaultIfUnset( 18625c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org config.targetLeveldBOv); 18635c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org config.digitalCompressionGaindB = 18645c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org options.rx_agc_digital_compression_gain.GetWithDefaultIfUnset( 18655c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org config.digitalCompressionGaindB); 18665c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org config.limiterEnable = options.rx_agc_limiter.GetWithDefaultIfUnset( 18675c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org config.limiterEnable); 18685c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org if (engine()->voe()->processing()->SetRxAgcConfig( 18695c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org voe_channel(), config) == -1) { 18705c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org LOG_RTCERR4(SetRxAgcConfig, voe_channel(), config.targetLeveldBOv, 18715c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org config.digitalCompressionGaindB, config.limiterEnable); 18725c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org return false; 18735c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org } 18745c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org } 187580303b162fe139828d0661df23e03f09126508acwu@webrtc.org if (dscp_option_changed) { 187680303b162fe139828d0661df23e03f09126508acwu@webrtc.org talk_base::DiffServCodePoint dscp = talk_base::DSCP_DEFAULT; 18778485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org if (options_.dscp.GetWithDefaultIfUnset(false)) 187880303b162fe139828d0661df23e03f09126508acwu@webrtc.org dscp = kAudioDscpValue; 187980303b162fe139828d0661df23e03f09126508acwu@webrtc.org if (MediaChannel::SetDscp(dscp) != 0) { 188080303b162fe139828d0661df23e03f09126508acwu@webrtc.org LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; 188180303b162fe139828d0661df23e03f09126508acwu@webrtc.org } 188280303b162fe139828d0661df23e03f09126508acwu@webrtc.org } 18835c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org 18840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Set voice channel options. Current options: " 18850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << options_.ToString(); 18860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 18870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 18880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 18890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetRecvCodecs( 18900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::vector<AudioCodec>& codecs) { 18910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Set the payload types to be used for incoming media. 18920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Setting receive voice codecs:"; 18930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 18940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<AudioCodec> new_codecs; 18950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Find all new codecs. We allow adding new codecs but don't allow changing 18960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // the payload type of codecs that is already configured since we might 18970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // already be receiving packets with that payload type. 18980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (std::vector<AudioCodec>::const_iterator it = codecs.begin(); 18997162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org it != codecs.end(); ++it) { 19000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AudioCodec old_codec; 19010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (FindCodec(recv_codecs_, *it, &old_codec)) { 19020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (old_codec.id != it->id) { 19030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_ERROR) << it->name << " payload type changed."; 19040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 19050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 19060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 19070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org new_codecs.push_back(*it); 19080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 19090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 19100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (new_codecs.empty()) { 19110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // There are no new codecs to configure. Already configured codecs are 19120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // never removed. 19130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 19140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 19150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 19160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (playout_) { 19170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Receive codecs can not be changed while playing. So we temporarily 19180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // pause playout. 19190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org PausePlayout(); 19200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 19210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 19227162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org bool ret = true; 19230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (std::vector<AudioCodec>::const_iterator it = new_codecs.begin(); 19240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org it != new_codecs.end() && ret; ++it) { 19250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::CodecInst voe_codec; 19260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->FindWebRtcCodec(*it, &voe_codec)) { 19270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << ToString(*it); 19280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_codec.pltype = it->id; 19297162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (default_receive_ssrc_ == 0) { 19307162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // Set the receive codecs on the default channel explicitly if the 19317162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // default channel is not used by |receive_channels_|, this happens in 19327162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // conference mode or in non-conference mode when there is no playout 19337162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // channel. 19347162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // TODO(xians): Figure out how we use the default channel in conference 19357162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // mode. 19367162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (engine()->voe()->codec()->SetRecPayloadType( 19377162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org voe_channel(), voe_codec) == -1) { 19387162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org LOG_RTCERR2(SetRecPayloadType, voe_channel(), ToString(voe_codec)); 19397162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org ret = false; 19407162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org } 19410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 19420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 19430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Set the receive codecs on all receiving channels. 19447162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org for (ChannelMap::iterator it = receive_channels_.begin(); 19457162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org it != receive_channels_.end() && ret; ++it) { 19460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->codec()->SetRecPayloadType( 1947b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org it->second->channel(), voe_codec) == -1) { 1948b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org LOG_RTCERR2(SetRecPayloadType, it->second->channel(), 19497162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org ToString(voe_codec)); 19500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ret = false; 19510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 19520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 19530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 19540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Unknown codec " << ToString(*it); 19550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ret = false; 19560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 19570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 19580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ret) { 19590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org recv_codecs_ = codecs; 19600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 19610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 19620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (desired_playout_ && !playout_) { 19630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ResumePlayout(); 19640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 19650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ret; 19660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 19670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 19680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetSendCodecs( 1969952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org int channel, const std::vector<AudioCodec>& codecs) { 197007617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org // Disable VAD, FEC, and RED unless we know the other side wants them. 1971952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org engine()->voe()->codec()->SetVADStatus(channel, false); 1972952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 197307617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#ifdef USE_WEBRTC_DEV_BRANCH 197407617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org engine()->voe()->rtp()->SetREDStatus(channel, false); 197507617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org engine()->voe()->codec()->SetFECStatus(channel, false); 197607617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#else 197707617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org // TODO(minyue): Remove code under #else case after new WebRTC roll. 1978952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org engine()->voe()->rtp()->SetFECStatus(channel, false); 197907617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#endif // USE_WEBRTC_DEV_BRANCH 19800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 19810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Scan through the list to figure out the codec to use for sending, along 19820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // with the proper configuration for VAD and DTMF. 19837587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org bool found_send_codec = false; 19840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::CodecInst send_codec; 19850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org memset(&send_codec, 0, sizeof(send_codec)); 19860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1987a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org bool nack_enabled = nack_enabled_; 1988a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org 19897587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // Set send codec (the first non-telephone-event/CN codec) 19900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (std::vector<AudioCodec>::const_iterator it = codecs.begin(); 19910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org it != codecs.end(); ++it) { 19920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Ignore codecs we don't know about. The negotiation step should prevent 19930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // this, but double-check to be sure. 19940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::CodecInst voe_codec; 19950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!engine()->FindWebRtcCodec(*it, &voe_codec)) { 19968485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org LOG(LS_WARNING) << "Unknown codec " << ToString(*it); 19970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org continue; 19980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 19990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 20007587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org if (IsTelephoneEventCodec(it->name) || IsCNCodec(it->name)) { 20017587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // Skip telephone-event/CN codec, which will be handled later. 20027587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org continue; 20037587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org } 20047587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 20050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If OPUS, change what we send according to the "stereo" codec 20060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // parameter, and not the "channels" parameter. We set 20070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // voe_codec.channels to 2 if "stereo=1" and 1 otherwise. If 20080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // the bitrate is not specified, i.e. is zero, we set it to the 20090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // appropriate default value for mono or stereo Opus. 20100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (IsOpus(*it)) { 20110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (IsOpusStereoEnabled(*it)) { 20120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_codec.channels = 2; 20137162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (!IsValidOpusBitrate(it->bitrate)) { 20147162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (it->bitrate != 0) { 20157162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org LOG(LS_WARNING) << "Overrides the invalid supplied bitrate(" 20167162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org << it->bitrate 20177162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org << ") with default opus stereo bitrate: " 20187162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org << kOpusStereoBitrate; 20197162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org } 20200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_codec.rate = kOpusStereoBitrate; 20210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 20220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 20230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_codec.channels = 1; 20247162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (!IsValidOpusBitrate(it->bitrate)) { 20257162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (it->bitrate != 0) { 20267162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org LOG(LS_WARNING) << "Overrides the invalid supplied bitrate(" 20277162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org << it->bitrate 20287162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org << ") with default opus mono bitrate: " 20297162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org << kOpusMonoBitrate; 20307162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org } 20310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_codec.rate = kOpusMonoBitrate; 20320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 20330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 20347162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org int bitrate_from_params = GetOpusBitrateFromParams(*it); 20357162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (bitrate_from_params != 0) { 20367162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org voe_codec.rate = bitrate_from_params; 20377162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org } 203807617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org 203902632fd0ce3e3625079f6472bd55370ed58509debuildbot@webrtc.org // For Opus, we also enable inband FEC if it is requested. 204007617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org if (IsOpusFecEnabled(*it)) { 204107617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org LOG(LS_INFO) << "Enabling Opus FEC on channel " << channel; 204207617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#ifdef USE_WEBRTC_DEV_BRANCH 204307617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) { 204407617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org // Enable in-band FEC of the Opus codec. Treat any failure as a fatal 204507617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org // internal error. 204607617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org LOG_RTCERR2(SetFECStatus, channel, true); 204707617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org return false; 204807617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org } 204907617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#endif // USE_WEBRTC_DEV_BRANCH 205007617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org } 20510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 20520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 20537587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // We'll use the first codec in the list to actually send audio data. 20547587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // Be sure to use the payload type requested by the remote side. 205507617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org // "red", for RED audio, is a special case where the actual codec to be 20567587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // used is specified in params. 20577587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org if (IsRedCodec(it->name)) { 20587587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // Parse out the RED parameters. If we fail, just ignore RED; 20597587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // we don't support all possible params/usage scenarios. 20607587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org if (!GetRedSendCodec(*it, codecs, &send_codec)) { 20617587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org continue; 20627587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org } 20637587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 20647587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // Enable redundant encoding of the specified codec. Treat any 20657587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // failure as a fatal internal error. 206607617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#ifdef USE_WEBRTC_DEV_BRANCH 206707617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org LOG(LS_INFO) << "Enabling RED on channel " << channel; 206807617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org if (engine()->voe()->rtp()->SetREDStatus(channel, true, it->id) == -1) { 206907617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org LOG_RTCERR3(SetREDStatus, channel, true, it->id); 207007617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#else 207107617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org // TODO(minyue): Remove code under #else case after new WebRTC roll. 20727587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org LOG(LS_INFO) << "Enabling FEC"; 20737587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org if (engine()->voe()->rtp()->SetFECStatus(channel, true, it->id) == -1) { 20747587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org LOG_RTCERR3(SetFECStatus, channel, true, it->id); 207507617d70029b9232bf7a5d8af375a3ac18a03836buildbot@webrtc.org#endif // USE_WEBRTC_DEV_BRANCH 20767587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org return false; 20777587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org } 20787587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org } else { 20797587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org send_codec = voe_codec; 2080a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org nack_enabled = IsNackEnabled(*it); 20817587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org } 20827587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org found_send_codec = true; 20837587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org break; 20847587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org } 20857587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 2086a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org if (nack_enabled_ != nack_enabled) { 2087a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org SetNack(channel, nack_enabled); 2088a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org nack_enabled_ = nack_enabled; 2089a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org } 2090a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org 20917587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org if (!found_send_codec) { 20927587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org LOG(LS_WARNING) << "Received empty list of codecs."; 20937587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org return false; 20947587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org } 20957587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 20967587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // Set the codec immediately, since SetVADStatus() depends on whether 20977587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // the current codec is mono or stereo. 20987587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org if (!SetSendCodec(channel, send_codec)) 20997587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org return false; 21007587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 21017587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // Always update the |send_codec_| to the currently set send codec. 21027587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org send_codec_.reset(new webrtc::CodecInst(send_codec)); 21037587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 21047587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org if (send_bw_setting_) { 21057587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org SetSendBandwidthInternal(send_bw_bps_); 21067587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org } 21077587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 21087587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // Loop through the codecs list again to config the telephone-event/CN codec. 21097587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org for (std::vector<AudioCodec>::const_iterator it = codecs.begin(); 21107587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org it != codecs.end(); ++it) { 21117587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // Ignore codecs we don't know about. The negotiation step should prevent 21127587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // this, but double-check to be sure. 21137587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org webrtc::CodecInst voe_codec; 21147587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org if (!engine()->FindWebRtcCodec(*it, &voe_codec)) { 21157587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org LOG(LS_WARNING) << "Unknown codec " << ToString(*it); 21167587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org continue; 21177587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org } 21187587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 2119f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Find the DTMF telephone event "codec" and tell VoiceEngine channels 2120f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // about it. 21217587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org if (IsTelephoneEventCodec(it->name)) { 2122952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org if (engine()->voe()->dtmf()->SetSendTelephoneEventPayloadType( 2123952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org channel, it->id) == -1) { 2124952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org LOG_RTCERR2(SetSendTelephoneEventPayloadType, channel, it->id); 2125952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org return false; 21260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 21277587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org } else if (IsCNCodec(it->name)) { 21287587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // Turn voice activity detection/comfort noise on if supported. 21297587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // Set the wideband CN payload type appropriately. 21307587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // (narrowband always uses the static payload type 13). 21310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::PayloadFrequencies cn_freq; 21320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org switch (it->clockrate) { 21330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case 8000: 21340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cn_freq = webrtc::kFreq8000Hz; 21350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 21360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case 16000: 21370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cn_freq = webrtc::kFreq16000Hz; 21380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 21390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case 32000: 21400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cn_freq = webrtc::kFreq32000Hz; 21410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 21420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org default: 21430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "CN frequency " << it->clockrate 21440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " not supported."; 21450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org continue; 21460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2147952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // Set the CN payloadtype and the VAD status. 2148952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // The CN payload type for 8000 Hz clockrate is fixed at 13. 2149952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org if (cn_freq != webrtc::kFreq8000Hz) { 2150952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org if (engine()->voe()->codec()->SetSendCNPayloadType( 2151952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org channel, it->id, cn_freq) == -1) { 2152952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org LOG_RTCERR3(SetSendCNPayloadType, channel, it->id, cn_freq); 2153952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // TODO(ajm): This failure condition will be removed from VoE. 2154952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // Restore the return here when we update to a new enough webrtc. 2155952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // 2156952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // Not returning false because the SetSendCNPayloadType will fail if 2157952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // the channel is already sending. 2158952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // This can happen if the remote description is applied twice, for 2159952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // example in the case of ROAP on top of JSEP, where both side will 2160952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // send the offer. 21610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2162952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org } 2163952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // Only turn on VAD if we have a CN payload type that matches the 2164952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // clockrate for the codec we are going to use. 2165952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org if (it->clockrate == send_codec.plfreq) { 2166952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org LOG(LS_INFO) << "Enabling VAD"; 2167952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) { 2168952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org LOG_RTCERR2(SetVADStatus, channel, true); 2169952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org return false; 21700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 21710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 21720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2173cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org } 2174952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org return true; 2175952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org} 2176952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org 2177952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.orgbool WebRtcVoiceMediaChannel::SetSendCodecs( 2178952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org const std::vector<AudioCodec>& codecs) { 2179952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org dtmf_allowed_ = false; 2180952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org for (std::vector<AudioCodec>::const_iterator it = codecs.begin(); 2181952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org it != codecs.end(); ++it) { 2182952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // Find the DTMF telephone event "codec". 2183952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org if (_stricmp(it->name.c_str(), "telephone-event") == 0 || 2184952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org _stricmp(it->name.c_str(), "audio/telephone-event") == 0) { 2185952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org dtmf_allowed_ = true; 2186952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org } 2187952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org } 2188952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org 2189952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // Cache the codecs in order to configure the channel created later. 2190952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org send_codecs_ = codecs; 2191952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org for (ChannelMap::iterator iter = send_channels_.begin(); 2192952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org iter != send_channels_.end(); ++iter) { 2193b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (!SetSendCodecs(iter->second->channel(), codecs)) { 21940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2195952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org } 21960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 21970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2198a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org // Set nack status on receive channels and update |nack_enabled_|. 2199952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org SetNack(receive_channels_, nack_enabled_); 22000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 22010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2202f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2203f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.orgvoid WebRtcVoiceMediaChannel::SetNack(const ChannelMap& channels, 2204f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org bool nack_enabled) { 2205f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org for (ChannelMap::const_iterator it = channels.begin(); 2206f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org it != channels.end(); ++it) { 2207b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org SetNack(it->second->channel(), nack_enabled); 2208f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 2209f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org} 2210f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2211952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.orgvoid WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) { 22120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (nack_enabled) { 2213952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org LOG(LS_INFO) << "Enabling NACK for channel " << channel; 22140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); 22150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 2216952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org LOG(LS_INFO) << "Disabling NACK for channel " << channel; 22170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 22180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 22190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 22200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 22210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetSendCodec( 22220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const webrtc::CodecInst& send_codec) { 22230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Selected voice codec " << ToString(send_codec) 22240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << ", bitrate=" << send_codec.rate; 2225f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org for (ChannelMap::iterator iter = send_channels_.begin(); 2226f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org iter != send_channels_.end(); ++iter) { 2227b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (!SetSendCodec(iter->second->channel(), send_codec)) 2228f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return false; 22290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2230f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2231f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return true; 2232f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org} 2233f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2234f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.orgbool WebRtcVoiceMediaChannel::SetSendCodec( 2235f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org int channel, const webrtc::CodecInst& send_codec) { 2236f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG(LS_INFO) << "Send channel " << channel << " selected voice codec " 2237f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org << ToString(send_codec) << ", bitrate=" << send_codec.rate; 2238f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2239a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org webrtc::CodecInst current_codec; 2240a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org if (engine()->voe()->codec()->GetSendCodec(channel, current_codec) == 0 && 2241a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org (send_codec == current_codec)) { 2242a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org // Codec is already configured, we can return without setting it again. 2243a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org return true; 2244a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org } 2245a32dfc68b5624bdc8e3901c1a91adb869f919ef8wu@webrtc.org 2246f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->codec()->SetSendCodec(channel, send_codec) == -1) { 2247f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG_RTCERR2(SetSendCodec, channel, ToString(send_codec)); 2248f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return false; 2249f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 22500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 22510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 22520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 22530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetRecvRtpHeaderExtensions( 22540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::vector<RtpHeaderExtension>& extensions) { 22552ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org if (receive_extensions_ == extensions) { 22562ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org return true; 22572ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org } 22582ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org 22592ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org // The default channel may or may not be in |receive_channels_|. Set the rtp 22602ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org // header extensions for default channel regardless. 22612ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org if (!SetChannelRecvRtpHeaderExtensions(voe_channel(), extensions)) { 22622ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org return false; 22632ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org } 22643ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org 22653ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org // Loop through all receive channels and enable/disable the extensions. 22663ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org for (ChannelMap::const_iterator channel_it = receive_channels_.begin(); 22673ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org channel_it != receive_channels_.end(); ++channel_it) { 22682ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org if (!SetChannelRecvRtpHeaderExtensions(channel_it->second->channel(), 22692ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org extensions)) { 22703ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org return false; 22713ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org } 22723ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org } 22732ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org 22742ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org receive_extensions_ = extensions; 22750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 22760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 22770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 22782ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.orgbool WebRtcVoiceMediaChannel::SetChannelRecvRtpHeaderExtensions( 22792ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org int channel_id, const std::vector<RtpHeaderExtension>& extensions) { 22802ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org#ifdef USE_WEBRTC_DEV_BRANCH 22813ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org const RtpHeaderExtension* audio_level_extension = 22823ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org FindHeaderExtension(extensions, kRtpAudioLevelHeaderExtension); 22833ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org if (!SetHeaderExtension( 22842ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org &webrtc::VoERTP_RTCP::SetReceiveAudioLevelIndicationStatus, channel_id, 22853ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org audio_level_extension)) { 22863ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org return false; 22873ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org } 22882ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org#endif // USE_WEBRTC_DEV_BRANCH 22892ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org 22902ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org const RtpHeaderExtension* send_time_extension = 22912ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension); 22923ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org if (!SetHeaderExtension( 22932ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org &webrtc::VoERTP_RTCP::SetReceiveAbsoluteSenderTimeStatus, channel_id, 22943ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org send_time_extension)) { 22953ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org return false; 22963ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org } 22972ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org return true; 22982ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org} 22992ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org 23002ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.orgbool WebRtcVoiceMediaChannel::SetSendRtpHeaderExtensions( 23012ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org const std::vector<RtpHeaderExtension>& extensions) { 23022ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org if (send_extensions_ == extensions) { 23032ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org return true; 23042ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org } 23052ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org 23062ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org // The default channel may or may not be in |send_channels_|. Set the rtp 23072ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org // header extensions for default channel regardless. 23082ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org 23092ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org if (!SetChannelSendRtpHeaderExtensions(voe_channel(), extensions)) { 23102ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org return false; 23112ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org } 23120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 23132ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org // Loop through all send channels and enable/disable the extensions. 23143ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org for (ChannelMap::const_iterator channel_it = send_channels_.begin(); 23153ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org channel_it != send_channels_.end(); ++channel_it) { 23162ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org if (!SetChannelSendRtpHeaderExtensions(channel_it->second->channel(), 23172ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org extensions)) { 23183ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org return false; 23193ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org } 23200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 23212ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org 23222ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org send_extensions_ = extensions; 23232ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org return true; 23242ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org} 23252ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org 23262ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.orgbool WebRtcVoiceMediaChannel::SetChannelSendRtpHeaderExtensions( 23272ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org int channel_id, const std::vector<RtpHeaderExtension>& extensions) { 23282ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org const RtpHeaderExtension* audio_level_extension = 23292ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org FindHeaderExtension(extensions, kRtpAudioLevelHeaderExtension); 23302ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org 23312ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org if (!SetHeaderExtension( 23322ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org &webrtc::VoERTP_RTCP::SetSendAudioLevelIndicationStatus, channel_id, 23332ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org audio_level_extension)) { 23342ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org return false; 23352ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org } 23362ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org 23372ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org const RtpHeaderExtension* send_time_extension = 23382ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension); 23392ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org if (!SetHeaderExtension( 23402ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org &webrtc::VoERTP_RTCP::SetSendAbsoluteSenderTimeStatus, channel_id, 23412ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org send_time_extension)) { 23422ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org return false; 23432ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org } 23442ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org 23450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 23460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 23470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 23480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetPlayout(bool playout) { 23490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org desired_playout_ = playout; 23500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ChangePlayout(desired_playout_); 23510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 23520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 23530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::PausePlayout() { 23540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ChangePlayout(false); 23550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 23560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 23570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::ResumePlayout() { 23580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ChangePlayout(desired_playout_); 23590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 23600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 23610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::ChangePlayout(bool playout) { 23620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (playout_ == playout) { 23630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 23640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 23650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 23667162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // Change the playout of all channels to the new state. 23670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool result = true; 23687162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (receive_channels_.empty()) { 23690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Only toggle the default channel if we don't have any other channels. 23700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org result = SetPlayout(voe_channel(), playout); 23710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 23727162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org for (ChannelMap::iterator it = receive_channels_.begin(); 23737162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org it != receive_channels_.end() && result; ++it) { 2374b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (!SetPlayout(it->second->channel(), playout)) { 23757162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org LOG(LS_ERROR) << "SetPlayout " << playout << " on channel " 2376b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org << it->second->channel() << " failed"; 23770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org result = false; 23780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 23790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 23800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 23810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (result) { 23820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org playout_ = playout; 23830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 23840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return result; 23850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 23860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 23870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetSend(SendFlags send) { 23880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org desired_send_ = send; 2389f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (!send_channels_.empty()) 23900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ChangeSend(desired_send_); 23910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 23920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 23930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 23940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::PauseSend() { 23950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ChangeSend(SEND_NOTHING); 23960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 23970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 23980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::ResumeSend() { 23990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ChangeSend(desired_send_); 24000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 24010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 24020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::ChangeSend(SendFlags send) { 24030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (send_ == send) { 24040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 24050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 24060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2407f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Change the settings on each send channel. 2408f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (send == SEND_MICROPHONE) 24090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine()->SetOptionOverrides(options_); 24100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2411f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Change the settings on each send channel. 2412f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org for (ChannelMap::iterator iter = send_channels_.begin(); 2413f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org iter != send_channels_.end(); ++iter) { 2414b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (!ChangeSend(iter->second->channel(), send)) 24150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2416f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 2417f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2418f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Clear up the options after stopping sending. 2419f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (send == SEND_NOTHING) 2420f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org engine()->ClearOptionOverrides(); 2421f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2422f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org send_ = send; 2423f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return true; 2424f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org} 2425f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2426f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.orgbool WebRtcVoiceMediaChannel::ChangeSend(int channel, SendFlags send) { 2427f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (send == SEND_MICROPHONE) { 2428f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->base()->StartSend(channel) == -1) { 2429f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG_RTCERR1(StartSend, channel); 24300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 24310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 24320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->file() && 2433f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org engine()->voe()->file()->StopPlayingFileAsMicrophone(channel) == -1) { 2434f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG_RTCERR1(StopPlayingFileAsMicrophone, channel); 24350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 24360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 24370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { // SEND_NOTHING 2438f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org ASSERT(send == SEND_NOTHING); 2439f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->base()->StopSend(channel) == -1) { 2440f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG_RTCERR1(StopSend, channel); 2441f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return false; 24420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2443f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 24440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2445f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return true; 2446f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org} 2447f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 24482ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org// TODO(ronghuawu): Change this method to return bool. 2449f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.orgvoid WebRtcVoiceMediaChannel::ConfigureSendChannel(int channel) { 2450f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->network()->RegisterExternalTransport( 2451f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org channel, *this) == -1) { 2452f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG_RTCERR2(RegisterExternalTransport, channel, this); 24530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2454f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2455f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Enable RTCP (for quality stats and feedback messages) 2456f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org EnableRtcp(channel); 2457f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2458f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Reset all recv codecs; they will be enabled via SetRecvCodecs. 2459f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org ResetRecvCodecs(channel); 24602ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org 24612ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org // Set RTP header extension for the new channel. 24622ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org SetChannelSendRtpHeaderExtensions(channel, send_extensions_); 2463f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org} 2464f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2465f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.orgbool WebRtcVoiceMediaChannel::DeleteChannel(int channel) { 2466f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->network()->DeRegisterExternalTransport(channel) == -1) { 2467f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG_RTCERR1(DeRegisterExternalTransport, channel); 2468f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 2469f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2470f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->base()->DeleteChannel(channel) == -1) { 2471f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG_RTCERR1(DeleteChannel, channel); 2472f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return false; 2473f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 2474f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 24750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 24760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 24770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 24780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) { 2479f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // If the default channel is already used for sending create a new channel 2480f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // otherwise use the default channel for sending. 2481f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org int channel = GetSendChannelNum(sp.first_ssrc()); 2482f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (channel != -1) { 2483f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG(LS_ERROR) << "Stream already exists with ssrc " << sp.first_ssrc(); 24840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 24850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 24860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2487f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org bool default_channel_is_available = true; 2488f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org for (ChannelMap::const_iterator iter = send_channels_.begin(); 2489f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org iter != send_channels_.end(); ++iter) { 2490b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (IsDefaultChannel(iter->second->channel())) { 2491f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org default_channel_is_available = false; 2492f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org break; 2493f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 2494f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 2495f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (default_channel_is_available) { 2496f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org channel = voe_channel(); 2497f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } else { 2498f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Create a new channel for sending audio data. 249997fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org channel = engine()->CreateMediaVoiceChannel(); 2500f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (channel == -1) { 2501f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG_RTCERR0(CreateChannel); 2502f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return false; 2503f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 2504f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2505f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org ConfigureSendChannel(channel); 2506f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 2507f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2508f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Save the channel to send_channels_, so that RemoveSendStream() can still 2509f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // delete the channel in case failure happens below. 2510b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org webrtc::AudioTransport* audio_transport = 2511b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org engine()->voe()->base()->audio_transport(); 2512b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org send_channels_.insert(std::make_pair( 2513b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org sp.first_ssrc(), 2514b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org new WebRtcVoiceChannelRenderer(channel, audio_transport))); 2515f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2516f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Set the send (local) SSRC. 2517f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // If there are multiple send SSRCs, we can only set the first one here, and 2518f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // the rest of the SSRC(s) need to be set after SetSendCodec has been called 2519f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // (with a codec requires multiple SSRC(s)). 2520f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->rtp()->SetLocalSSRC(channel, sp.first_ssrc()) == -1) { 2521f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG_RTCERR2(SetSendSSRC, channel, sp.first_ssrc()); 25220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 25230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2524f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2525f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // At this point the channel's local SSRC has been updated. If the channel is 2526f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // the default channel make sure that all the receive channels are updated as 2527f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // well. Receive channels have to have the same SSRC as the default channel in 2528f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // order to send receiver reports with this SSRC. 2529f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (IsDefaultChannel(channel)) { 2530f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org for (ChannelMap::const_iterator it = receive_channels_.begin(); 2531f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org it != receive_channels_.end(); ++it) { 2532f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Only update the SSRC for non-default channels. 2533b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (!IsDefaultChannel(it->second->channel())) { 2534b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (engine()->voe()->rtp()->SetLocalSSRC(it->second->channel(), 2535f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sp.first_ssrc()) != 0) { 2536b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org LOG_RTCERR2(SetLocalSSRC, it->second->channel(), sp.first_ssrc()); 2537f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return false; 2538f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 25397162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org } 25400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 25410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 25420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2543f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->rtp()->SetRTCP_CNAME(channel, sp.cname.c_str()) == -1) { 2544f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG_RTCERR2(SetRTCP_CNAME, channel, sp.cname); 25450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 25460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 25470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2548952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org // Set the current codecs to be used for the new channel. 2549952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org if (!send_codecs_.empty() && !SetSendCodecs(channel, send_codecs_)) 2550f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return false; 25517162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 2552f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return ChangeSend(channel, desired_send_); 25530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 25540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 25550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::RemoveSendStream(uint32 ssrc) { 2556f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org ChannelMap::iterator it = send_channels_.find(ssrc); 2557f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (it == send_channels_.end()) { 2558f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc 2559f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org << " which doesn't exist."; 25600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 25610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 25627162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 2563b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org int channel = it->second->channel(); 2564f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org ChangeSend(channel, SEND_NOTHING); 2565f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2566b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // Delete the WebRtcVoiceChannelRenderer object connected to the channel, 2567b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // this will disconnect the audio renderer with the send channel. 2568b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org delete it->second; 2569b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org send_channels_.erase(it); 2570f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2571f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (IsDefaultChannel(channel)) { 2572f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Do not delete the default channel since the receive channels depend on 2573f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // the default channel, recycle it instead. 2574f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org ChangeSend(channel, SEND_NOTHING); 2575f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } else { 2576f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Clean up and delete the send channel. 2577f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG(LS_INFO) << "Removing audio send stream " << ssrc 2578f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org << " with VoiceEngine channel #" << channel << "."; 2579f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (!DeleteChannel(channel)) 2580f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return false; 2581f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 2582f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 2583f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (send_channels_.empty()) 2584f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org ChangeSend(SEND_NOTHING); 25857162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 25860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 25870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 25880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 25890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { 25907162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org talk_base::CritScope lock(&receive_channels_cs_); 25910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 25920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!VERIFY(sp.ssrcs.size() == 1)) 25930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 25940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 ssrc = sp.first_ssrc(); 25950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2596861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org if (ssrc == 0) { 2597861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org LOG(LS_WARNING) << "AddRecvStream with 0 ssrc is not supported."; 2598861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org return false; 2599861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org } 2600861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org 26017162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (receive_channels_.find(ssrc) != receive_channels_.end()) { 26027162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc; 26030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 26040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 26050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 26067162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // Reuse default channel for recv stream in non-conference mode call 26077162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // when the default channel is not being used. 2608b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org webrtc::AudioTransport* audio_transport = 2609b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org engine()->voe()->base()->audio_transport(); 26107162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (!InConferenceMode() && default_receive_ssrc_ == 0) { 26117162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org LOG(LS_INFO) << "Recv stream " << sp.first_ssrc() 26127162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org << " reuse default channel"; 26137162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org default_receive_ssrc_ = sp.first_ssrc(); 26147162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org receive_channels_.insert(std::make_pair( 2615b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org default_receive_ssrc_, 2616b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org new WebRtcVoiceChannelRenderer(voe_channel(), audio_transport))); 26177162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org return SetPlayout(voe_channel(), playout_); 26187162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org } 26197162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 26200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Create a new channel for receiving audio data. 262197fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org int channel = engine()->CreateMediaVoiceChannel(); 26220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (channel == -1) { 26230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR0(CreateChannel); 26240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 26250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 26260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2627861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org if (!ConfigureRecvChannel(channel)) { 2628861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org DeleteChannel(channel); 2629861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org return false; 2630861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org } 2631861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org 2632861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org receive_channels_.insert( 2633b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org std::make_pair( 2634b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org ssrc, new WebRtcVoiceChannelRenderer(channel, audio_transport))); 2635861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org 2636861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org LOG(LS_INFO) << "New audio stream " << ssrc 2637861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org << " registered to VoiceEngine channel #" 2638861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org << channel << "."; 2639861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org return true; 2640861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org} 2641861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.org 2642861d07361a4559a72e96236f27b758a56f6f59f0wu@webrtc.orgbool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) { 26430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Configure to use external transport, like our default channel. 26440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->network()->RegisterExternalTransport( 26450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel, *this) == -1) { 26460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR2(SetExternalTransport, channel, this); 26470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 26480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 26490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 26500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Use the same SSRC as our default channel (so the RTCP reports are correct). 26518485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org unsigned int send_ssrc = 0; 26520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::VoERTP_RTCP* rtp = engine()->voe()->rtp(); 26530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (rtp->GetLocalSSRC(voe_channel(), send_ssrc) == -1) { 26548485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org LOG_RTCERR1(GetSendSSRC, channel); 26550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 26560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 26570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (rtp->SetLocalSSRC(channel, send_ssrc) == -1) { 26588485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org LOG_RTCERR1(SetSendSSRC, channel); 26590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 26600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 26610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 26620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Use the same recv payload types as our default channel. 26630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ResetRecvCodecs(channel); 26640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!recv_codecs_.empty()) { 26650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (std::vector<AudioCodec>::const_iterator it = recv_codecs_.begin(); 26660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org it != recv_codecs_.end(); ++it) { 26670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::CodecInst voe_codec; 26680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->FindWebRtcCodec(*it, &voe_codec)) { 26690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_codec.pltype = it->id; 26700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_codec.rate = 0; // Needed to make GetRecPayloadType work for ISAC 26710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->codec()->GetRecPayloadType( 26720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_channel(), voe_codec) != -1) { 26730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->codec()->SetRecPayloadType( 26740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel, voe_codec) == -1) { 26750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); 26760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 26770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 26780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 26790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 26800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 26810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 26820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 26837162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (InConferenceMode()) { 26847162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // To be in par with the video, voe_channel() is not used for receiving in 26857162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // a conference call. 26867162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (receive_channels_.empty() && default_receive_ssrc_ == 0 && playout_) { 26877162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // This is the first stream in a multi user meeting. We can now 26887162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // disable playback of the default stream. This since the default 26897162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // stream will probably have received some initial packets before 26907162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // the new stream was added. This will mean that the CN state from 26917162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // the default channel will be mixed in with the other streams 26927162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // throughout the whole meeting, which might be disturbing. 26937162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org LOG(LS_INFO) << "Disabling playback on the default voice channel"; 26947162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org SetPlayout(voe_channel(), false); 26957162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org } 26960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2697952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org SetNack(channel, nack_enabled_); 26980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 26992ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org // Set RTP header extension for the new channel. 27002ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org if (!SetChannelRecvRtpHeaderExtensions(channel, receive_extensions_)) { 27012ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org return false; 27022ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org } 27032ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org 27040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return SetPlayout(channel, playout_); 27050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 27060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 27070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32 ssrc) { 27087162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org talk_base::CritScope lock(&receive_channels_cs_); 27097162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org ChannelMap::iterator it = receive_channels_.find(ssrc); 2710f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (it == receive_channels_.end()) { 2711f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc 2712f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org << " which doesn't exist."; 27137162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org return false; 2714f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 27150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2716b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // Delete the WebRtcVoiceChannelRenderer object connected to the channel, this 2717b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // will disconnect the audio renderer with the receive channel. 2718b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org // Cache the channel before the deletion. 2719b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org const int channel = it->second->channel(); 2720b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org delete it->second; 2721b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org receive_channels_.erase(it); 2722b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org 27237162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (ssrc == default_receive_ssrc_) { 2724b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org ASSERT(IsDefaultChannel(channel)); 27257162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // Recycle the default channel is for recv stream. 27267162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (playout_) 27277162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org SetPlayout(voe_channel(), false); 27287162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 27297162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org default_receive_ssrc_ = 0; 27307162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org return true; 27317162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org } 27327162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 27337162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org LOG(LS_INFO) << "Removing audio stream " << ssrc 2734b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org << " with VoiceEngine channel #" << channel << "."; 2735b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (!DeleteChannel(channel)) 27367162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org return false; 27377162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 27387162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org bool enable_default_channel_playout = false; 27397162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (receive_channels_.empty()) { 27407162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // The last stream was removed. We can now enable the default 27417162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // channel for new channels to be played out immediately without 27427162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // waiting for AddStream messages. 27437162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // We do this for both conference mode and non-conference mode. 27447162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // TODO(oja): Does the default channel still have it's CN state? 27457162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org enable_default_channel_playout = true; 27467162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org } 27477162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (!InConferenceMode() && receive_channels_.size() == 1 && 27487162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org default_receive_ssrc_ != 0) { 27497162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // Only the default channel is active, enable the playout on default 27507162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // channel. 27517162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org enable_default_channel_playout = true; 27527162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org } 27537162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (enable_default_channel_playout && playout_) { 27547162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org LOG(LS_INFO) << "Enabling playback on the default voice channel"; 27557162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org SetPlayout(voe_channel(), true); 27567162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org } 27577162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 27587162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org return true; 27597162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org} 27607162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 27617162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetRemoteRenderer(uint32 ssrc, 27627162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org AudioRenderer* renderer) { 27637162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org ChannelMap::iterator it = receive_channels_.find(ssrc); 27647162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (it == receive_channels_.end()) { 27657162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (renderer) { 27667162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // Return an error if trying to set a valid renderer with an invalid ssrc. 2767f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG(LS_ERROR) << "SetRemoteRenderer failed with ssrc "<< ssrc; 27680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 27690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 27700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 27717162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // The channel likely has gone away, do nothing. 27727162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org return true; 27737162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org } 27747162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 2775b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (renderer) 2776b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org it->second->Start(renderer); 2777b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org else 2778b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org it->second->Stop(); 27797162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 27800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 27810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 27820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 27837162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetLocalRenderer(uint32 ssrc, 27847162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org AudioRenderer* renderer) { 2785f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org ChannelMap::iterator it = send_channels_.find(ssrc); 2786f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (it == send_channels_.end()) { 2787f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (renderer) { 2788f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Return an error if trying to set a valid renderer with an invalid ssrc. 2789f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG(LS_ERROR) << "SetLocalRenderer failed with ssrc "<< ssrc; 2790f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return false; 2791f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 27927162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 2793f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // The channel likely has gone away, do nothing. 2794f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return true; 27957162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org } 27960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2797b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (renderer) 2798b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org it->second->Start(renderer); 2799b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org else 2800b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org it->second->Stop(); 28017162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org 28020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 28030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 28040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 28050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::GetActiveStreams( 28060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AudioInfo::StreamList* actives) { 28077162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // In conference mode, the default channel should not be in 28087162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // |receive_channels_|. 28090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org actives->clear(); 28107162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org for (ChannelMap::iterator it = receive_channels_.begin(); 28117162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org it != receive_channels_.end(); ++it) { 2812b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org int level = GetOutputLevel(it->second->channel()); 28130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (level > 0) { 28140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org actives->push_back(std::make_pair(it->first, level)); 28150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 28160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 28170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 28180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 28190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 28200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceMediaChannel::GetOutputLevel() { 28210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // return the highest output level of all streams 28220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int highest = GetOutputLevel(voe_channel()); 28237162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org for (ChannelMap::iterator it = receive_channels_.begin(); 28247162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org it != receive_channels_.end(); ++it) { 2825b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org int level = GetOutputLevel(it->second->channel()); 28260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org highest = talk_base::_max(level, highest); 28270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 28280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return highest; 28290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 28300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 28310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceMediaChannel::GetTimeSinceLastTyping() { 28320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int ret; 28330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->processing()->TimeSinceLastTyping(ret) == -1) { 28340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // In case of error, log the info and continue 28350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR0(TimeSinceLastTyping); 28360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ret = -1; 28370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 28380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ret *= 1000; // We return ms, webrtc returns seconds. 28390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 28400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ret; 28410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 28420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 28430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceMediaChannel::SetTypingDetectionParameters(int time_window, 28440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int cost_per_typing, int reporting_threshold, int penalty_decay, 28450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int type_event_delay) { 28460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->processing()->SetTypingDetectionParameters( 28470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org time_window, cost_per_typing, 28480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org reporting_threshold, penalty_decay, type_event_delay) == -1) { 28490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // In case of error, log the info and continue 28500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR5(SetTypingDetectionParameters, time_window, 28510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cost_per_typing, reporting_threshold, penalty_decay, 28520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org type_event_delay); 28530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 28540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 28550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 28560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetOutputScaling( 28570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 ssrc, double left, double right) { 28587162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org talk_base::CritScope lock(&receive_channels_cs_); 28590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Collect the channels to scale the output volume. 28600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<int> channels; 28610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (0 == ssrc) { // Collect all channels, including the default one. 28627162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // Default channel is not in receive_channels_ if it is not being used for 28637162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // playout. 28647162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (default_receive_ssrc_ == 0) 28657162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org channels.push_back(voe_channel()); 28667162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org for (ChannelMap::const_iterator it = receive_channels_.begin(); 28677162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org it != receive_channels_.end(); ++it) { 2868b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org channels.push_back(it->second->channel()); 28690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 28700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { // Collect only the channel of the specified ssrc. 28710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int channel = GetReceiveChannelNum(ssrc); 28720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (-1 == channel) { 28730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Cannot find channel for ssrc:" << ssrc; 28740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 28750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 28760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channels.push_back(channel); 28770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 28780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 28790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Scale the output volume for the collected channels. We first normalize to 28800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // scale the volume and then set the left and right pan. 28810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org float scale = static_cast<float>(talk_base::_max(left, right)); 28820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (scale > 0.0001f) { 28830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org left /= scale; 28840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org right /= scale; 28850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 28860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (std::vector<int>::const_iterator it = channels.begin(); 28870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org it != channels.end(); ++it) { 28880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (-1 == engine()->voe()->volume()->SetChannelOutputVolumeScaling( 28890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *it, scale)) { 28900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR2(SetChannelOutputVolumeScaling, *it, scale); 28910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 28920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 28930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (-1 == engine()->voe()->volume()->SetOutputVolumePan( 28940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *it, static_cast<float>(left), static_cast<float>(right))) { 28950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR3(SetOutputVolumePan, *it, left, right); 28960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Do not return if fails. SetOutputVolumePan is not available for all 28970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // pltforms. 28980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 28990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "SetOutputScaling to left=" << left * scale 29000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " right=" << right * scale 29010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " for channel " << *it << " and ssrc " << ssrc; 29020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 29030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 29040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 29050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::GetOutputScaling( 29070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 ssrc, double* left, double* right) { 29080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!left || !right) return false; 29090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29107162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org talk_base::CritScope lock(&receive_channels_cs_); 29110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Determine which channel based on ssrc. 29120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int channel = (0 == ssrc) ? voe_channel() : GetReceiveChannelNum(ssrc); 29130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (channel == -1) { 29140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Cannot find channel for ssrc:" << ssrc; 29150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 29160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 29170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org float scaling; 29190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (-1 == engine()->voe()->volume()->GetChannelOutputVolumeScaling( 29200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel, scaling)) { 29210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR2(GetChannelOutputVolumeScaling, channel, scaling); 29220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 29230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 29240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org float left_pan; 29260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org float right_pan; 29270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (-1 == engine()->voe()->volume()->GetOutputVolumePan( 29280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel, left_pan, right_pan)) { 29290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR3(GetOutputVolumePan, channel, left_pan, right_pan); 29300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If GetOutputVolumePan fails, we use the default left and right pan. 29310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org left_pan = 1.0f; 29320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org right_pan = 1.0f; 29330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 29340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *left = scaling * left_pan; 29360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *right = scaling * right_pan; 29370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 29380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 29390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetRingbackTone(const char *buf, int len) { 29410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ringback_tone_.reset(new WebRtcSoundclipStream(buf, len)); 29420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 29430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 29440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::PlayRingbackTone(uint32 ssrc, 29460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool play, bool loop) { 29470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ringback_tone_) { 29480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 29490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 29500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The voe file api is not available in chrome. 29520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!engine()->voe()->file()) { 29530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 29540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 29550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Determine which VoiceEngine channel to play on. 29570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int channel = (ssrc == 0) ? voe_channel() : GetReceiveChannelNum(ssrc); 29580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (channel == -1) { 29590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 29600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 29610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Make sure the ringtone is cued properly, and play it out. 29630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (play) { 29640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ringback_tone_->set_loop(loop); 29650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ringback_tone_->Rewind(); 29660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->file()->StartPlayingFileLocally(channel, 29670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ringback_tone_.get()) == -1) { 29680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR2(StartPlayingFileLocally, channel, ringback_tone_.get()); 29690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_ERROR) << "Unable to start ringback tone"; 29700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 29710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 29720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ringback_channels_.insert(channel); 29730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Started ringback on channel " << channel; 29740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 29750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->file()->IsPlayingFileLocally(channel) == 1 && 29760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine()->voe()->file()->StopPlayingFileLocally(channel) == -1) { 29770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR1(StopPlayingFileLocally, channel); 29780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 29790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 29800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Stopped ringback on channel " << channel; 29810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ringback_channels_.erase(channel); 29820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 29830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 29850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 29860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::CanInsertDtmf() { 29880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return dtmf_allowed_; 29890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 29900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::InsertDtmf(uint32 ssrc, int event, 29920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int duration, int flags) { 29930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!dtmf_allowed_) { 29940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 29950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 29960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 29970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Send the event. 29980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (flags & cricket::DF_SEND) { 2999952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org int channel = -1; 3000952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org if (ssrc == 0) { 3001952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org bool default_channel_is_inuse = false; 3002952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org for (ChannelMap::const_iterator iter = send_channels_.begin(); 3003952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org iter != send_channels_.end(); ++iter) { 3004b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (IsDefaultChannel(iter->second->channel())) { 3005952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org default_channel_is_inuse = true; 3006952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org break; 3007952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org } 3008952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org } 3009952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org if (default_channel_is_inuse) { 3010952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org channel = voe_channel(); 3011952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org } else if (!send_channels_.empty()) { 3012b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org channel = send_channels_.begin()->second->channel(); 3013952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org } 3014952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org } else { 3015952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org channel = GetSendChannelNum(ssrc); 3016952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org } 3017f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (channel == -1) { 30180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "InsertDtmf - The specified ssrc " 30190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << ssrc << " is not in use."; 30200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 30210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 30220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Send DTMF using out-of-band DTMF. ("true", as 3rd arg) 3023f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->dtmf()->SendTelephoneEvent( 3024f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org channel, event, true, duration) == -1) { 3025f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG_RTCERR4(SendTelephoneEvent, channel, event, true, duration); 30260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 30270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 30280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 30290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 30300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Play the event. 30310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (flags & cricket::DF_PLAY) { 30320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Play DTMF tone locally. 30330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->dtmf()->PlayDtmfTone(event, duration) == -1) { 30340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR2(PlayDtmfTone, event, duration); 30350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 30360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 30370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 30380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 30390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 30400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 30410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3042f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.orgvoid WebRtcVoiceMediaChannel::OnPacketReceived( 3043f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) { 30440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Pick which channel to send this packet to. If this packet doesn't match 30450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // any multiplexed streams, just send it to the default channel. Otherwise, 30460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // send it to the specific decoder instance for that stream. 30470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int which_channel = GetReceiveChannelNum( 30480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseSsrc(packet->data(), packet->length(), false)); 30490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (which_channel == -1) { 30500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org which_channel = voe_channel(); 30510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 30520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 30530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Stop any ringback that might be playing on the channel. 30540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // It's possible the ringback has already stopped, ih which case we'll just 30550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // use the opportunity to remove the channel from ringback_channels_. 30560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->file()) { 30570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::set<int>::iterator it = ringback_channels_.find(which_channel); 30580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (it != ringback_channels_.end()) { 30590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->file()->IsPlayingFileLocally( 30600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org which_channel) == 1) { 30610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine()->voe()->file()->StopPlayingFileLocally(which_channel); 30620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Stopped ringback on channel " << which_channel 30630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " due to incoming media"; 30640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 30650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ringback_channels_.erase(which_channel); 30660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 30670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 30680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 30690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Pass it off to the decoder. 30701a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org engine()->voe()->network()->ReceivedRTPPacket( 30711a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org which_channel, 30721a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org packet->data(), 30731a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org static_cast<unsigned int>(packet->length())); 30740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 30750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3076f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.orgvoid WebRtcVoiceMediaChannel::OnRtcpReceived( 3077f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) { 3078f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Sending channels need all RTCP packets with feedback information. 3079f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Even sender reports can contain attached report blocks. 3080f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Receiving channels need sender reports in order to create 3081f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // correct receiver reports. 3082f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org int type = 0; 3083f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (!GetRtcpType(packet->data(), packet->length(), &type)) { 3084f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG(LS_WARNING) << "Failed to parse type from received RTCP packet"; 3085f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return; 3086f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 3087f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 3088f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // If it is a sender report, find the channel that is listening. 3089f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org bool has_sent_to_default_channel = false; 3090f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (type == kRtcpTypeSR) { 3091f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org int which_channel = GetReceiveChannelNum( 3092f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org ParseSsrc(packet->data(), packet->length(), true)); 3093f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (which_channel != -1) { 3094f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org engine()->voe()->network()->ReceivedRTCPPacket( 3095f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org which_channel, 3096f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org packet->data(), 3097f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org static_cast<unsigned int>(packet->length())); 3098f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 3099f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (IsDefaultChannel(which_channel)) 3100f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org has_sent_to_default_channel = true; 3101f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 3102f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 3103f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 3104f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // SR may continue RR and any RR entry may correspond to any one of the send 3105f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // channels. So all RTCP packets must be forwarded all send channels. VoE 3106f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // will filter out RR internally. 3107f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org for (ChannelMap::iterator iter = send_channels_.begin(); 3108f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org iter != send_channels_.end(); ++iter) { 3109f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Make sure not sending the same packet to default channel more than once. 3110b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (IsDefaultChannel(iter->second->channel()) && 3111b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org has_sent_to_default_channel) 3112f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org continue; 31130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3114f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org engine()->voe()->network()->ReceivedRTCPPacket( 3115b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org iter->second->channel(), 3116f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org packet->data(), 3117f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org static_cast<unsigned int>(packet->length())); 3118f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 31190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 31200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 31210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::MuteStream(uint32 ssrc, bool muted) { 3122f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org int channel = (ssrc == 0) ? voe_channel() : GetSendChannelNum(ssrc); 3123f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (channel == -1) { 31240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use."; 31250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 31260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3127f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->volume()->SetInputMute(channel, muted) == -1) { 3128f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG_RTCERR2(SetInputMute, channel, muted); 31290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 31300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 31310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 31320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 31330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3134f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.orgbool WebRtcVoiceMediaChannel::SetStartSendBandwidth(int bps) { 3135f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org // TODO(andresp): Add support for setting an independent start bandwidth when 3136f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org // bandwidth estimation is enabled for voice engine. 3137f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org return false; 3138f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org} 31390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3140f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.orgbool WebRtcVoiceMediaChannel::SetMaxSendBandwidth(int bps) { 3141f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org LOG(LS_INFO) << "WebRtcVoiceMediaChanne::SetSendBandwidth."; 3142cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org 3143f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org return SetSendBandwidthInternal(bps); 3144cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org} 3145cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org 3146f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.orgbool WebRtcVoiceMediaChannel::SetSendBandwidthInternal(int bps) { 3147f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendBandwidthInternal."; 3148f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org 3149f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org send_bw_setting_ = true; 3150f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org send_bw_bps_ = bps; 3151cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org 31520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!send_codec_) { 3153cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org LOG(LS_INFO) << "The send codec has not been set up yet. " 3154cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org << "The send bandwidth setting will be applied later."; 3155cc712021a90cc93a68b4e65930cd0a0ad0a88d4ewu@webrtc.org return true; 31560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 31570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 31580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Bandwidth is auto by default. 3159f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by 3160f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org // SetMaxSendBandwith(0), the second call removes the previous limit. 3161f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org if (bps <= 0) 31620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 31630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 31640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::CodecInst codec = *send_codec_; 31650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool is_multi_rate = IsCodecMultiRate(codec); 31660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 31670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (is_multi_rate) { 31680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If codec is multi-rate then just set the bitrate. 31690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org codec.rate = bps; 31700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!SetSendCodec(codec)) { 31710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Failed to set codec " << codec.plname 31720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " to bitrate " << bps << " bps."; 31730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 31740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 31750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 31760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 31770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If codec is not multi-rate and |bps| is less than the fixed bitrate 31780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // then fail. If codec is not multi-rate and |bps| exceeds or equal the 31790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // fixed bitrate then ignore. 31800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (bps < codec.rate) { 31810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Failed to set codec " << codec.plname 31820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " to bitrate " << bps << " bps" 31830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << ", requires at least " << codec.rate << " bps."; 31840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 31850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 31860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 31870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 31880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 31890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 31900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) { 31910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool echo_metrics_on = false; 31920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // These can take on valid negative values, so use the lowest possible level 31930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // as default rather than -1. 3194f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org int echo_return_loss = -100; 3195f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org int echo_return_loss_enhancement = -100; 31960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // These can also be negative, but in practice -1 is only used to signal 31970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // insufficient data, since the resolution is limited to multiples of 4 ms. 3198f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org int echo_delay_median_ms = -1; 3199f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org int echo_delay_std_ms = -1; 3200f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->processing()->GetEcMetricsStatus( 3201f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org echo_metrics_on) != -1 && echo_metrics_on) { 32020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(ajm): we may want to use VoECallReport::GetEchoMetricsSummary 32030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // here, but it appears to be unsuitable currently. Revisit after this is 32040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // investigated: http://b/issue?id=5666755 32050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int erl, erle, rerl, anlp; 3206f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->processing()->GetEchoMetrics( 3207f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org erl, erle, rerl, anlp) != -1) { 3208f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org echo_return_loss = erl; 3209f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org echo_return_loss_enhancement = erle; 32100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 32110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 32120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int median, std; 32130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->processing()->GetEcDelayMetrics(median, std) != -1) { 3214f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org echo_delay_median_ms = median; 3215f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org echo_delay_std_ms = std; 32160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 32170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 32180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3219f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org webrtc::CallStatistics cs; 3220f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org unsigned int ssrc; 3221f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org webrtc::CodecInst codec; 3222f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org unsigned int level; 3223f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 3224f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org for (ChannelMap::const_iterator channel_iter = send_channels_.begin(); 3225f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org channel_iter != send_channels_.end(); ++channel_iter) { 3226b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org const int channel = channel_iter->second->channel(); 3227f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 3228f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Fill in the sender info, based on what we know, and what the 3229f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // remote side told us it got from its RTCP report. 3230f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org VoiceSenderInfo sinfo; 3231f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 3232f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->rtp()->GetRTCPStatistics(channel, cs) == -1 || 3233f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org engine()->voe()->rtp()->GetLocalSSRC(channel, ssrc) == -1) { 3234f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org continue; 3235f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 3236f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 323797fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org sinfo.add_ssrc(ssrc); 3238f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.codec_name = send_codec_.get() ? send_codec_->plname : ""; 3239f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.bytes_sent = cs.bytesSent; 3240f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.packets_sent = cs.packetsSent; 3241f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // RTT isn't known until a RTCP report is received. Until then, VoiceEngine 3242f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // returns 0 to indicate an error value. 3243f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.rtt_ms = (cs.rttMs > 0) ? cs.rttMs : -1; 3244f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 3245f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Get data from the last remote RTCP report. Use default values if no data 3246f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // available. 3247f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.fraction_lost = -1.0; 3248f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.jitter_ms = -1; 3249f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.packets_lost = -1; 3250f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.ext_seqnum = -1; 3251f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org std::vector<webrtc::ReportBlock> receive_blocks; 3252f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->rtp()->GetRemoteRTCPReportBlocks( 3253f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org channel, &receive_blocks) != -1 && 3254f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org engine()->voe()->codec()->GetSendCodec(channel, codec) != -1) { 3255f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org std::vector<webrtc::ReportBlock>::iterator iter; 3256f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org for (iter = receive_blocks.begin(); iter != receive_blocks.end(); 3257f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org ++iter) { 3258f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Lookup report for send ssrc only. 325997fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org if (iter->source_SSRC == sinfo.ssrc()) { 3260f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Convert Q8 to floating point. 3261f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.fraction_lost = static_cast<float>(iter->fraction_lost) / 256; 3262f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Convert samples to milliseconds. 3263f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (codec.plfreq / 1000 > 0) { 3264f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.jitter_ms = iter->interarrival_jitter / (codec.plfreq / 1000); 3265f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 3266f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.packets_lost = iter->cumulative_num_packets_lost; 3267f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.ext_seqnum = iter->extended_highest_sequence_number; 3268f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org break; 3269f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 3270f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 3271f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 3272f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 3273f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Local speech level. 3274f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.audio_level = (engine()->voe()->volume()-> 3275f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org GetSpeechInputLevelFullRange(level) != -1) ? level : -1; 3276f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 3277f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // TODO(xians): We are injecting the same APM logging to all the send 3278f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // channels here because there is no good way to know which send channel 3279f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // is using the APM. The correct fix is to allow the send channels to have 3280f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // their own APM so that we can feed the correct APM logging to different 3281f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // send channels. See issue crbug/264611 . 3282f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.echo_return_loss = echo_return_loss; 3283f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.echo_return_loss_enhancement = echo_return_loss_enhancement; 3284f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.echo_delay_median_ms = echo_delay_median_ms; 3285f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org sinfo.echo_delay_std_ms = echo_delay_std_ms; 32865528070a0c76057a000b877fc56ca4180ad2087bmallinath@webrtc.org // TODO(ajm): Re-enable this metric once we have a reliable implementation. 32875528070a0c76057a000b877fc56ca4180ad2087bmallinath@webrtc.org sinfo.aec_quality_min = -1; 32884ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org sinfo.typing_noise_detected = typing_noise_detected_; 3289f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 3290f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org info->senders.push_back(sinfo); 3291f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 32920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 32937162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // Build the list of receivers, one for each receiving channel, or 1 in 32947162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org // a 1:1 call. 32950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<int> channels; 32967162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org for (ChannelMap::const_iterator it = receive_channels_.begin(); 32977162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org it != receive_channels_.end(); ++it) { 3298b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org channels.push_back(it->second->channel()); 32990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 33000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (channels.empty()) { 33010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channels.push_back(voe_channel()); 33020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 33030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 33040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Get the SSRC and stats for each receiver, based on our own calculations. 33050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (std::vector<int>::const_iterator it = channels.begin(); 33060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org it != channels.end(); ++it) { 33070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org memset(&cs, 0, sizeof(cs)); 33080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->rtp()->GetRemoteSSRC(*it, ssrc) != -1 && 33090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine()->voe()->rtp()->GetRTCPStatistics(*it, cs) != -1 && 33100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine()->voe()->codec()->GetRecCodec(*it, codec) != -1) { 33110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org VoiceReceiverInfo rinfo; 331297fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org rinfo.add_ssrc(ssrc); 33130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org rinfo.bytes_rcvd = cs.bytesReceived; 33140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org rinfo.packets_rcvd = cs.packetsReceived; 33150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The next four fields are from the most recently sent RTCP report. 33160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Convert Q8 to floating point. 33170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org rinfo.fraction_lost = static_cast<float>(cs.fractionLost) / (1 << 8); 33180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org rinfo.packets_lost = cs.cumulativeLost; 33190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org rinfo.ext_seqnum = cs.extendedMax; 3320842c369caaf7ab0115e101686ee5640a289da0e8buildbot@webrtc.org#ifdef USE_WEBRTC_DEV_BRANCH 3321842c369caaf7ab0115e101686ee5640a289da0e8buildbot@webrtc.org rinfo.capture_start_ntp_time_ms = cs.capture_start_ntp_time_ms_; 3322842c369caaf7ab0115e101686ee5640a289da0e8buildbot@webrtc.org#endif 3323ec0b1b83d70e08f3bd47940d33ad69cb8bb0878fbuildbot@webrtc.org if (codec.pltype != -1) { 3324ec0b1b83d70e08f3bd47940d33ad69cb8bb0878fbuildbot@webrtc.org rinfo.codec_name = codec.plname; 3325ec0b1b83d70e08f3bd47940d33ad69cb8bb0878fbuildbot@webrtc.org } 33260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Convert samples to milliseconds. 33270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (codec.plfreq / 1000 > 0) { 33280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org rinfo.jitter_ms = cs.jitterSamples / (codec.plfreq / 1000); 33290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 33300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 33310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Get jitter buffer and total delay (alg + jitter + playout) stats. 33320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::NetworkStatistics ns; 33330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->neteq() && 33340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine()->voe()->neteq()->GetNetworkStatistics( 33350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *it, ns) != -1) { 33360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org rinfo.jitter_buffer_ms = ns.currentBufferSize; 33370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org rinfo.jitter_buffer_preferred_ms = ns.preferredBufferSize; 33380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org rinfo.expand_rate = 33391a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org static_cast<float>(ns.currentExpandRate) / (1 << 14); 33400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 334154caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org 334254caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org webrtc::AudioDecodingCallStats ds; 334354caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org if (engine()->voe()->neteq() && 334454caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org engine()->voe()->neteq()->GetDecodingCallStatistics( 334554caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org *it, &ds) != -1) { 334654caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org rinfo.decoding_calls_to_silence_generator = 334754caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org ds.calls_to_silence_generator; 334854caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org rinfo.decoding_calls_to_neteq = ds.calls_to_neteq; 334954caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org rinfo.decoding_normal = ds.decoded_normal; 335054caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org rinfo.decoding_plc = ds.decoded_plc; 335154caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org rinfo.decoding_cng = ds.decoded_cng; 335254caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org rinfo.decoding_plc_cng = ds.decoded_plc_cng; 335354caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org } 335454caffdda86e16e40218943b755a502c23b0940dhenrike@webrtc.org 33550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->sync()) { 335619da4659bfe1cd99b6b1476cae9bc74e99e0b09dsergeyu@chromium.org int jitter_buffer_delay_ms = 0; 33570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int playout_buffer_delay_ms = 0; 33580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine()->voe()->sync()->GetDelayEstimate( 335919da4659bfe1cd99b6b1476cae9bc74e99e0b09dsergeyu@chromium.org *it, &jitter_buffer_delay_ms, &playout_buffer_delay_ms); 336019da4659bfe1cd99b6b1476cae9bc74e99e0b09dsergeyu@chromium.org rinfo.delay_estimate_ms = jitter_buffer_delay_ms + 336119da4659bfe1cd99b6b1476cae9bc74e99e0b09dsergeyu@chromium.org playout_buffer_delay_ms; 33620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 33630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 33640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Get speech level. 33650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org rinfo.audio_level = (engine()->voe()->volume()-> 33660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org GetSpeechOutputLevelFullRange(*it, level) != -1) ? level : -1; 33670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org info->receivers.push_back(rinfo); 33680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 33690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 33700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 33710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 33720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 33730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 33740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceMediaChannel::GetLastMediaError( 33750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32* ssrc, VoiceMediaChannel::Error* error) { 33760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(ssrc != NULL); 33770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(error != NULL); 33780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org FindSsrc(voe_channel(), ssrc); 33790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *error = WebRtcErrorToChannelError(GetLastEngineError()); 33800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 33810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 33820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::FindSsrc(int channel_num, uint32* ssrc) { 33837162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org talk_base::CritScope lock(&receive_channels_cs_); 33840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(ssrc != NULL); 3385f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (channel_num == -1 && send_ != SEND_NOTHING) { 33860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Sometimes the VoiceEngine core will throw error with channel_num = -1. 33870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // This means the error is not limited to a specific channel. Signal the 33880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // message using ssrc=0. If the current channel is sending, use this 33890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // channel for sending the message. 33900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *ssrc = 0; 33910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 33920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 3393f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // Check whether this is a sending channel. 3394f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org for (ChannelMap::const_iterator it = send_channels_.begin(); 3395f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org it != send_channels_.end(); ++it) { 3396b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (it->second->channel() == channel_num) { 3397f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org // This is a sending channel. 3398f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org uint32 local_ssrc = 0; 3399f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (engine()->voe()->rtp()->GetLocalSSRC( 3400f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org channel_num, local_ssrc) != -1) { 3401f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org *ssrc = local_ssrc; 3402f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 3403f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return true; 3404f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 3405f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org } 3406f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 34070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Check whether this is a receiving channel. 34087162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org for (ChannelMap::const_iterator it = receive_channels_.begin(); 34097162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org it != receive_channels_.end(); ++it) { 3410b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (it->second->channel() == channel_num) { 34110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *ssrc = it->first; 34120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 34130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 34140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 34150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 34160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 34170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 34180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 34190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WebRtcVoiceMediaChannel::OnError(uint32 ssrc, int error) { 34204ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org if (error == VE_TYPING_NOISE_WARNING) { 34214ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org typing_noise_detected_ = true; 34224ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org } else if (error == VE_TYPING_NOISE_OFF_WARNING) { 34234ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org typing_noise_detected_ = false; 34244ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org } 34250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SignalMediaError(ssrc, WebRtcErrorToChannelError(error)); 34260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 34270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 34280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceMediaChannel::GetOutputLevel(int channel) { 34290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org unsigned int ulevel; 34300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int ret = 34310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine()->voe()->volume()->GetSpeechOutputLevel(channel, ulevel); 34320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (ret == 0) ? static_cast<int>(ulevel) : -1; 34330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 34340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 34350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceMediaChannel::GetReceiveChannelNum(uint32 ssrc) { 34367162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org ChannelMap::iterator it = receive_channels_.find(ssrc); 34377162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (it != receive_channels_.end()) 3438b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org return it->second->channel(); 34390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (ssrc == default_receive_ssrc_) ? voe_channel() : -1; 34400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 34410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 34420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcVoiceMediaChannel::GetSendChannelNum(uint32 ssrc) { 3443f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org ChannelMap::iterator it = send_channels_.find(ssrc); 3444f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org if (it != send_channels_.end()) 3445b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org return it->second->channel(); 3446f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 3447f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return -1; 34480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 34490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 34500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec, 34510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::vector<AudioCodec>& all_codecs, webrtc::CodecInst* send_codec) { 34520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Get the RED encodings from the parameter with no name. This may 34530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // change based on what is discussed on the Jingle list. 34540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The encoding parameter is of the form "a/b"; we only support where 34550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // a == b. Verify this and parse out the value into red_pt. 34560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If the parameter value is absent (as it will be until we wire up the 34570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // signaling of this message), use the second codec specified (i.e. the 34580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // one after "red") as the encoding parameter. 34590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int red_pt = -1; 34600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string red_params; 34610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CodecParameterMap::const_iterator it = red_codec.params.find(""); 34620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (it != red_codec.params.end()) { 34630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org red_params = it->second; 34640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<std::string> red_pts; 34650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (talk_base::split(red_params, '/', &red_pts) != 2 || 34660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org red_pts[0] != red_pts[1] || 34670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org !talk_base::FromString(red_pts[0], &red_pt)) { 34680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "RED params " << red_params << " not supported."; 34690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 34700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 34710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (red_codec.params.empty()) { 34720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "RED params not present, using defaults"; 34730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (all_codecs.size() > 1) { 34740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org red_pt = all_codecs[1].id; 34750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 34760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 34770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 34780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Try to find red_pt in |codecs|. 34790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<AudioCodec>::const_iterator codec; 34800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (codec = all_codecs.begin(); codec != all_codecs.end(); ++codec) { 34810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (codec->id == red_pt) 34820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 34830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 34840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 34850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If we find the right codec, that will be the codec we pass to 34860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // SetSendCodec, with the desired payload type. 34870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (codec != all_codecs.end() && 34880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine()->FindWebRtcCodec(*codec, send_codec)) { 34890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 34900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "RED params " << red_params << " are invalid."; 34910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 34920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 34930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 34940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 34950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 34960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 34970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::EnableRtcp(int channel) { 34980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->rtp()->SetRTCPStatus(channel, true) == -1) { 3499f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org LOG_RTCERR2(SetRTCPStatus, channel, 1); 35000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 35010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 35020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(juberti): Enable VQMon and RTCP XR reports, once we know what 35030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // what we want to do with them. 35040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // engine()->voe().EnableVQMon(voe_channel(), true); 35050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // engine()->voe().EnableRTCP_XR(voe_channel(), true); 35060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 35070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 35080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 35090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::ResetRecvCodecs(int channel) { 35100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int ncodecs = engine()->voe()->codec()->NumOfCodecs(); 35110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (int i = 0; i < ncodecs; ++i) { 35120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org webrtc::CodecInst voe_codec; 35130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->codec()->GetCodec(i, voe_codec) != -1) { 35140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org voe_codec.pltype = -1; 35150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->codec()->SetRecPayloadType( 35160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel, voe_codec) == -1) { 35170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); 35180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 35190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 35200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 35210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 35220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 35230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 35240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 35250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) { 35260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (playout) { 35270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Starting playout for channel #" << channel; 35280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (engine()->voe()->base()->StartPlayout(channel) == -1) { 35290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_RTCERR1(StartPlayout, channel); 35300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 35310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 35320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 35330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Stopping playout for channel #" << channel; 35340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org engine()->voe()->base()->StopPlayout(channel); 35350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 35360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 35370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 35380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 35390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orguint32 WebRtcVoiceMediaChannel::ParseSsrc(const void* data, size_t len, 35400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool rtcp) { 35410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org size_t ssrc_pos = (!rtcp) ? 8 : 4; 35420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 ssrc = 0; 35430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (len >= (ssrc_pos + sizeof(ssrc))) { 35440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ssrc = talk_base::GetBE32(static_cast<const char*>(data) + ssrc_pos); 35450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 35460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ssrc; 35470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 35480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 35490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Convert VoiceEngine error code into VoiceMediaChannel::Error enum. 35500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgVoiceMediaChannel::Error 35510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WebRtcVoiceMediaChannel::WebRtcErrorToChannelError(int err_code) { 35520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org switch (err_code) { 35530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case 0: 35540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ERROR_NONE; 35550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_CANNOT_START_RECORDING: 35560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_MIC_VOL_ERROR: 35570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_GET_MIC_VOL_ERROR: 35580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_CANNOT_ACCESS_MIC_VOL: 35590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ERROR_REC_DEVICE_OPEN_FAILED; 35600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_SATURATION_WARNING: 35610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ERROR_REC_DEVICE_SATURATION; 35620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_REC_DEVICE_REMOVED: 35630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ERROR_REC_DEVICE_REMOVED; 35640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_RUNTIME_REC_WARNING: 35650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_RUNTIME_REC_ERROR: 35660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ERROR_REC_RUNTIME_ERROR; 35670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_CANNOT_START_PLAYOUT: 35680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_SPEAKER_VOL_ERROR: 35690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_GET_SPEAKER_VOL_ERROR: 35700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_CANNOT_ACCESS_SPEAKER_VOL: 35710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ERROR_PLAY_DEVICE_OPEN_FAILED; 35720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_RUNTIME_PLAY_WARNING: 35730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_RUNTIME_PLAY_ERROR: 35740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ERROR_PLAY_RUNTIME_ERROR; 35750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case VE_TYPING_NOISE_WARNING: 35760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ERROR_REC_TYPING_NOISE_DETECTED; 35770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org default: 35780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return VoiceMediaChannel::ERROR_OTHER; 35790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 35800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 35810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 35823ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.orgbool WebRtcVoiceMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter, 35833ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org int channel_id, const RtpHeaderExtension* extension) { 35843ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org bool enable = false; 35852ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org int id = 0; 35862ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org std::string uri; 35873ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org if (extension) { 35883ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org enable = true; 35893ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org id = extension->id; 35902ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org uri = extension->uri; 35913ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org } 35923ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org if ((engine()->voe()->rtp()->*setter)(channel_id, enable, id) != 0) { 35932ccf00b08449e81bc72367010d65f4210f7fb60ebuildbot@webrtc.org LOG_RTCERR4(*setter, uri, channel_id, enable, id); 35943ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org return false; 35953ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org } 35963ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org return true; 35973ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org} 35983ca77cb43bc675f562521d4c90e8156a6e088cbchenrike@webrtc.org 35990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcSoundclipStream::Read(void *buf, int len) { 36000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org size_t res = 0; 36010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org mem_.Read(buf, len, &res, NULL); 36021a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org return static_cast<int>(res); 36030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 36040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 36050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint WebRtcSoundclipStream::Rewind() { 36060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org mem_.Rewind(); 36070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Return -1 to keep VoiceEngine from looping. 36080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (loop_) ? 0 : -1; 36090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 36100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 36110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // namespace cricket 36120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 36130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // HAVE_WEBRTC_VOICE 3614