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