1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
279af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  Use of this source code is governed by a BSD-style license
5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  that can be found in the LICENSE file in the root of the source
6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  tree. An additional intellectual property rights grant can be found
7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  in the file PATENTS.  All contributing project authors may
8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  be found in the AUTHORS file in the root of the source tree.
9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
11956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/voe_external_media_impl.h"
12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1398f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
1498f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/trace.h"
15956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/channel.h"
16956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/include/voe_errors.h"
17956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/output_mixer.h"
18956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/transmit_mixer.h"
19956aa7e0874f2e08c335a82a2c32f400fac8b031pbos@webrtc.org#include "webrtc/voice_engine/voice_engine_impl.h"
20470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
21470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comnamespace webrtc {
22470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
230d266054acece70259fc1e85026194154f41e5a0Jelena MarusicVoEExternalMedia* VoEExternalMedia::GetInterface(VoiceEngine* voiceEngine) {
24470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API
250d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return NULL;
26470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#else
270d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (NULL == voiceEngine) {
280d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return NULL;
290d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
300d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
310d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  s->AddRef();
320d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return s;
33470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
34470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
35470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
36470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API
37470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
38851becd00ce814f0e02a5c5a56ac0322a7f9494dtommi@webrtc.orgVoEExternalMediaImpl::VoEExternalMediaImpl(voe::SharedData* shared)
393f9db3735ee760803fbd687189743b22747f6e54wjia@webrtc.org    :
403f9db3735ee760803fbd687189743b22747f6e54wjia@webrtc.org#ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT
410d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      playout_delay_ms_(0),
423f9db3735ee760803fbd687189743b22747f6e54wjia@webrtc.org#endif
430d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      shared_(shared) {
440d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(shared_->instance_id(), -1),
450d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "VoEExternalMediaImpl() - ctor");
46470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
47470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
480d266054acece70259fc1e85026194154f41e5a0Jelena MarusicVoEExternalMediaImpl::~VoEExternalMediaImpl() {
490d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(shared_->instance_id(), -1),
500d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "~VoEExternalMediaImpl() - dtor");
51470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
52470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
53470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEExternalMediaImpl::RegisterExternalMediaProcessing(
54470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    int channel,
55470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    ProcessingTypes type,
560d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    VoEMediaProcess& processObject) {
570d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(shared_->instance_id(), -1),
580d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "RegisterExternalMediaProcessing(channel=%d, type=%d, "
590d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "processObject=0x%x)",
600d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               channel, type, &processObject);
610d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!shared_->statistics().Initialized()) {
620d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    shared_->SetLastError(VE_NOT_INITED, kTraceError);
630d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
640d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
650d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  switch (type) {
660d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kPlaybackPerChannel:
670d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kRecordingPerChannel: {
680d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
690d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      voe::Channel* channelPtr = ch.channel();
700d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      if (channelPtr == NULL) {
710d266054acece70259fc1e85026194154f41e5a0Jelena Marusic        shared_->SetLastError(
720d266054acece70259fc1e85026194154f41e5a0Jelena Marusic            VE_CHANNEL_NOT_VALID, kTraceError,
730d266054acece70259fc1e85026194154f41e5a0Jelena Marusic            "RegisterExternalMediaProcessing() failed to locate "
740d266054acece70259fc1e85026194154f41e5a0Jelena Marusic            "channel");
75470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
760d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      }
770d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      return channelPtr->RegisterExternalMediaProcessing(type, processObject);
78470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
790d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kPlaybackAllChannelsMixed: {
800d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      return shared_->output_mixer()->RegisterExternalMediaProcessing(
810d266054acece70259fc1e85026194154f41e5a0Jelena Marusic          processObject);
82470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
830d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kRecordingAllChannelsMixed:
840d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kRecordingPreprocessing: {
850d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      return shared_->transmit_mixer()->RegisterExternalMediaProcessing(
860d266054acece70259fc1e85026194154f41e5a0Jelena Marusic          &processObject, type);
870d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    }
880d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
890d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return -1;
90470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
91470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
92470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint VoEExternalMediaImpl::DeRegisterExternalMediaProcessing(
93470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    int channel,
940d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    ProcessingTypes type) {
950d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(shared_->instance_id(), -1),
960d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "DeRegisterExternalMediaProcessing(channel=%d)", channel);
970d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!shared_->statistics().Initialized()) {
980d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    shared_->SetLastError(VE_NOT_INITED, kTraceError);
990d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1000d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1010d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  switch (type) {
1020d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kPlaybackPerChannel:
1030d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kRecordingPerChannel: {
1040d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
1050d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      voe::Channel* channelPtr = ch.channel();
1060d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      if (channelPtr == NULL) {
1070d266054acece70259fc1e85026194154f41e5a0Jelena Marusic        shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
1080d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                              "RegisterExternalMediaProcessing() "
1090d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                              "failed to locate channel");
110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1110d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      }
1120d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      return channelPtr->DeRegisterExternalMediaProcessing(type);
113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1140d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kPlaybackAllChannelsMixed: {
1150d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      return shared_->output_mixer()->DeRegisterExternalMediaProcessing();
116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1170d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kRecordingAllChannelsMixed:
1180d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    case kRecordingPreprocessing: {
1190d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      return shared_->transmit_mixer()->DeRegisterExternalMediaProcessing(type);
1200d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    }
1210d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1220d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return -1;
123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1251b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.comint VoEExternalMediaImpl::GetAudioFrame(int channel, int desired_sample_rate_hz,
1261b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com                                        AudioFrame* frame) {
1270d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!shared_->statistics().Initialized()) {
1280d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    shared_->SetLastError(VE_NOT_INITED, kTraceError);
1290d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1300d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1310d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
1320d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::Channel* channelPtr = ch.channel();
1330d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (channelPtr == NULL) {
1340d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
1350d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "GetAudioFrame() failed to locate channel");
1360d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1370d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1380d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!channelPtr->ExternalMixing()) {
1390d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    shared_->SetLastError(VE_INVALID_OPERATION, kTraceError,
1400d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "GetAudioFrame() was called on channel that is not"
1410d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          " externally mixed.");
1420d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1430d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1440d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!channelPtr->Playing()) {
1450d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    shared_->SetLastError(
1460d266054acece70259fc1e85026194154f41e5a0Jelena Marusic        VE_INVALID_OPERATION, kTraceError,
1470d266054acece70259fc1e85026194154f41e5a0Jelena Marusic        "GetAudioFrame() was called on channel that is not playing.");
1480d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1490d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1500d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (desired_sample_rate_hz == -1) {
1510d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    shared_->SetLastError(VE_BAD_ARGUMENT, kTraceError,
1520d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "GetAudioFrame() was called with bad sample rate.");
1530d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1540d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1550d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  frame->sample_rate_hz_ =
1560d266054acece70259fc1e85026194154f41e5a0Jelena Marusic      desired_sample_rate_hz == 0 ? -1 : desired_sample_rate_hz;
1570f4b3731c34e796da92572380855dbc7321c8cfeminyuel  return channelPtr->GetAudioFrame(channel, frame);
1581b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com}
1591b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com
1601b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.comint VoEExternalMediaImpl::SetExternalMixing(int channel, bool enable) {
1610d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
1620d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               VoEId(shared_->instance_id(), channel),
1630d266054acece70259fc1e85026194154f41e5a0Jelena Marusic               "SetExternalMixing(channel=%d, enable=%d)", channel, enable);
1640d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (!shared_->statistics().Initialized()) {
1650d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    shared_->SetLastError(VE_NOT_INITED, kTraceError);
1660d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1670d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1680d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
1690d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  voe::Channel* channelPtr = ch.channel();
1700d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  if (channelPtr == NULL) {
1710d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
1720d266054acece70259fc1e85026194154f41e5a0Jelena Marusic                          "SetExternalMixing() failed to locate channel");
1730d266054acece70259fc1e85026194154f41e5a0Jelena Marusic    return -1;
1740d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  }
1750d266054acece70259fc1e85026194154f41e5a0Jelena Marusic  return channelPtr->SetExternalMixing(enable);
1761b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com}
1771b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com
178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif  // WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API
179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}  // namespace webrtc
181