1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org#include "webrtc/voice_engine/voe_external_media_impl.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
14471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org#include "webrtc/system_wrappers/interface/trace.h"
15471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org#include "webrtc/voice_engine/channel.h"
16471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org#include "webrtc/voice_engine/include/voe_errors.h"
17471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org#include "webrtc/voice_engine/output_mixer.h"
18471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org#include "webrtc/voice_engine/transmit_mixer.h"
19471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org#include "webrtc/voice_engine/voice_engine_impl.h"
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc {
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVoEExternalMedia* VoEExternalMedia::GetInterface(VoiceEngine* voiceEngine)
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifndef WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return NULL;
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#else
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (NULL == voiceEngine)
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return NULL;
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
32b9e5a3d589349ee55e41cb54eca4ec822018f5c5tommi@webrtc.org    VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    s->AddRef();
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return s;
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVoEExternalMediaImpl::VoEExternalMediaImpl(voe::SharedData* shared)
417b1e78d5a3ffef0815e2d3a8cb082a6ec0766708wjia@webrtc.org    :
427b1e78d5a3ffef0815e2d3a8cb082a6ec0766708wjia@webrtc.org#ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT
437b1e78d5a3ffef0815e2d3a8cb082a6ec0766708wjia@webrtc.org    playout_delay_ms_(0),
447b1e78d5a3ffef0815e2d3a8cb082a6ec0766708wjia@webrtc.org#endif
457b1e78d5a3ffef0815e2d3a8cb082a6ec0766708wjia@webrtc.org    shared_(shared)
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(shared_->instance_id(), -1),
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 "VoEExternalMediaImpl() - ctor");
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVoEExternalMediaImpl::~VoEExternalMediaImpl()
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(shared_->instance_id(), -1),
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 "~VoEExternalMediaImpl() - dtor");
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint VoEExternalMediaImpl::RegisterExternalMediaProcessing(
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int channel,
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ProcessingTypes type,
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    VoEMediaProcess& processObject)
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(shared_->instance_id(), -1),
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 "RegisterExternalMediaProcessing(channel=%d, type=%d, "
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 "processObject=0x%x)", channel, type, &processObject);
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!shared_->statistics().Initialized())
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        shared_->SetLastError(VE_NOT_INITED, kTraceError);
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    switch (type)
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        case kPlaybackPerChannel:
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        case kRecordingPerChannel:
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
75b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org            voe::ChannelOwner ch =
76b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org                shared_->channel_manager().GetChannel(channel);
77b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org            voe::Channel* channelPtr = ch.channel();
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if (channelPtr == NULL)
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    "RegisterExternalMediaProcessing() failed to locate "
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    "channel");
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                return -1;
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            return channelPtr->RegisterExternalMediaProcessing(type,
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                                               processObject);
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        case kPlaybackAllChannelsMixed:
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            return shared_->output_mixer()->RegisterExternalMediaProcessing(
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                processObject);
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        case kRecordingAllChannelsMixed:
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        case kRecordingPreprocessing:
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            return shared_->transmit_mixer()->RegisterExternalMediaProcessing(
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                &processObject, type);
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint VoEExternalMediaImpl::DeRegisterExternalMediaProcessing(
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int channel,
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ProcessingTypes type)
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(shared_->instance_id(), -1),
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 "DeRegisterExternalMediaProcessing(channel=%d)", channel);
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!shared_->statistics().Initialized())
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        shared_->SetLastError(VE_NOT_INITED, kTraceError);
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    switch (type)
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        case kPlaybackPerChannel:
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        case kRecordingPerChannel:
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
119b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org            voe::ChannelOwner ch =
120b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org                shared_->channel_manager().GetChannel(channel);
121b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org            voe::Channel* channelPtr = ch.channel();
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if (channelPtr == NULL)
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    "RegisterExternalMediaProcessing() "
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    "failed to locate channel");
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                return -1;
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            return channelPtr->DeRegisterExternalMediaProcessing(type);
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        case kPlaybackAllChannelsMixed:
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            return shared_->output_mixer()->
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                DeRegisterExternalMediaProcessing();
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        case kRecordingAllChannelsMixed:
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        case kRecordingPreprocessing:
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            return shared_->transmit_mixer()->
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                DeRegisterExternalMediaProcessing(type);
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
146b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comint VoEExternalMediaImpl::GetAudioFrame(int channel, int desired_sample_rate_hz,
147b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com                                        AudioFrame* frame) {
148b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
149b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com                 VoEId(shared_->instance_id(), channel),
150b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com                 "GetAudioFrame(channel=%d, desired_sample_rate_hz=%d)",
151b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com                 channel, desired_sample_rate_hz);
152b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    if (!shared_->statistics().Initialized())
153b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    {
154b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com        shared_->SetLastError(VE_NOT_INITED, kTraceError);
155b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com        return -1;
156b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    }
157b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org    voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
158b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org    voe::Channel* channelPtr = ch.channel();
159b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    if (channelPtr == NULL)
160b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    {
161b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com        shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
162b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com            "GetAudioFrame() failed to locate channel");
163b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com        return -1;
164b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    }
165b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    if (!channelPtr->ExternalMixing()) {
166b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com        shared_->SetLastError(VE_INVALID_OPERATION, kTraceError,
167b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com            "GetAudioFrame() was called on channel that is not"
168b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com            " externally mixed.");
169b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com        return -1;
170b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    }
171b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    if (!channelPtr->Playing()) {
172b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com        shared_->SetLastError(VE_INVALID_OPERATION, kTraceError,
173b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com            "GetAudioFrame() was called on channel that is not playing.");
174b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com        return -1;
175b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    }
176b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    if (desired_sample_rate_hz == -1) {
177b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com          shared_->SetLastError(VE_BAD_ARGUMENT, kTraceError,
178b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com              "GetAudioFrame() was called with bad sample rate.");
179b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com          return -1;
180b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    }
181b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    frame->sample_rate_hz_ = desired_sample_rate_hz == 0 ? -1 :
182b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com                             desired_sample_rate_hz;
183b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    return channelPtr->GetAudioFrame(channel, *frame);
184b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com}
185b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com
186b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comint VoEExternalMediaImpl::SetExternalMixing(int channel, bool enable) {
187b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
188b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com                 VoEId(shared_->instance_id(), channel),
189b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com                 "SetExternalMixing(channel=%d, enable=%d)", channel, enable);
190b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    if (!shared_->statistics().Initialized())
191b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    {
192b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com        shared_->SetLastError(VE_NOT_INITED, kTraceError);
193b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com        return -1;
194b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    }
195b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org    voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
196b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org    voe::Channel* channelPtr = ch.channel();
197b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    if (channelPtr == NULL)
198b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    {
199b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com        shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
200b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com            "SetExternalMixing() failed to locate channel");
201b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com        return -1;
202b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    }
203b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com    return channelPtr->SetExternalMixing(enable);
204b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com}
205b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif  // WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace webrtc
209