1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
6
7#include "base/logging.h"
8#include "content/renderer/media/media_stream_audio_processor.h"
9#include "content/renderer/media/webrtc/webrtc_audio_sink_adapter.h"
10#include "content/renderer/media/webrtc_local_audio_track.h"
11#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
12
13namespace content {
14
15static const char kAudioTrackKind[] = "audio";
16
17scoped_refptr<WebRtcLocalAudioTrackAdapter>
18WebRtcLocalAudioTrackAdapter::Create(
19    const std::string& label,
20    webrtc::AudioSourceInterface* track_source) {
21  rtc::RefCountedObject<WebRtcLocalAudioTrackAdapter>* adapter =
22      new rtc::RefCountedObject<WebRtcLocalAudioTrackAdapter>(
23          label, track_source);
24  return adapter;
25}
26
27WebRtcLocalAudioTrackAdapter::WebRtcLocalAudioTrackAdapter(
28    const std::string& label,
29    webrtc::AudioSourceInterface* track_source)
30    : webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(label),
31      owner_(NULL),
32      track_source_(track_source),
33      signal_level_(0) {
34}
35
36WebRtcLocalAudioTrackAdapter::~WebRtcLocalAudioTrackAdapter() {
37}
38
39void WebRtcLocalAudioTrackAdapter::Initialize(WebRtcLocalAudioTrack* owner) {
40  DCHECK(!owner_);
41  DCHECK(owner);
42  owner_ = owner;
43}
44
45void WebRtcLocalAudioTrackAdapter::SetAudioProcessor(
46    const scoped_refptr<MediaStreamAudioProcessor>& processor) {
47  base::AutoLock auto_lock(lock_);
48  audio_processor_ = processor;
49}
50
51std::string WebRtcLocalAudioTrackAdapter::kind() const {
52  return kAudioTrackKind;
53}
54
55void WebRtcLocalAudioTrackAdapter::AddSink(
56    webrtc::AudioTrackSinkInterface* sink) {
57  DCHECK(sink);
58#ifndef NDEBUG
59  // Verify that |sink| has not been added.
60  for (ScopedVector<WebRtcAudioSinkAdapter>::const_iterator it =
61           sink_adapters_.begin();
62       it != sink_adapters_.end(); ++it) {
63    DCHECK(!(*it)->IsEqual(sink));
64  }
65#endif
66
67  scoped_ptr<WebRtcAudioSinkAdapter> adapter(
68      new WebRtcAudioSinkAdapter(sink));
69  owner_->AddSink(adapter.get());
70  sink_adapters_.push_back(adapter.release());
71}
72
73void WebRtcLocalAudioTrackAdapter::RemoveSink(
74    webrtc::AudioTrackSinkInterface* sink) {
75  DCHECK(sink);
76  for (ScopedVector<WebRtcAudioSinkAdapter>::iterator it =
77           sink_adapters_.begin();
78       it != sink_adapters_.end(); ++it) {
79    if ((*it)->IsEqual(sink)) {
80      owner_->RemoveSink(*it);
81      sink_adapters_.erase(it);
82      return;
83    }
84  }
85}
86
87bool WebRtcLocalAudioTrackAdapter::GetSignalLevel(int* level) {
88  base::AutoLock auto_lock(lock_);
89  // It is required to provide the signal level after audio processing. In
90  // case the audio processing is not enabled for the track, we return
91  // false here in order not to overwrite the value from WebRTC.
92  // TODO(xians): Remove this after we turn on the APM in Chrome by default.
93  // http://crbug/365672 .
94  if (!MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled())
95    return false;
96
97  *level = signal_level_;
98  return true;
99}
100
101rtc::scoped_refptr<webrtc::AudioProcessorInterface>
102WebRtcLocalAudioTrackAdapter::GetAudioProcessor() {
103  base::AutoLock auto_lock(lock_);
104  return audio_processor_.get();
105}
106
107std::vector<int> WebRtcLocalAudioTrackAdapter::VoeChannels() const {
108  base::AutoLock auto_lock(lock_);
109  return voe_channels_;
110}
111
112void WebRtcLocalAudioTrackAdapter::SetSignalLevel(int signal_level) {
113  base::AutoLock auto_lock(lock_);
114  signal_level_ = signal_level;
115}
116
117void WebRtcLocalAudioTrackAdapter::AddChannel(int channel_id) {
118  DVLOG(1) << "WebRtcLocalAudioTrack::AddChannel(channel_id="
119           << channel_id << ")";
120  base::AutoLock auto_lock(lock_);
121  if (std::find(voe_channels_.begin(), voe_channels_.end(), channel_id) !=
122      voe_channels_.end()) {
123    // We need to handle the case when the same channel is connected to the
124    // track more than once.
125    return;
126  }
127
128  voe_channels_.push_back(channel_id);
129}
130
131void WebRtcLocalAudioTrackAdapter::RemoveChannel(int channel_id) {
132  DVLOG(1) << "WebRtcLocalAudioTrack::RemoveChannel(channel_id="
133           << channel_id << ")";
134  base::AutoLock auto_lock(lock_);
135  std::vector<int>::iterator iter =
136      std::find(voe_channels_.begin(), voe_channels_.end(), channel_id);
137  DCHECK(iter != voe_channels_.end());
138  voe_channels_.erase(iter);
139}
140
141webrtc::AudioSourceInterface* WebRtcLocalAudioTrackAdapter::GetSource() const {
142  return track_source_;
143}
144
145cricket::AudioRenderer* WebRtcLocalAudioTrackAdapter::GetRenderer() {
146  // When the audio track processing is enabled, return a NULL so that capture
147  // data goes through Libjingle LocalAudioTrackHandler::LocalAudioSinkAdapter
148  // ==> WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer ==> WebRTC.
149  // When the audio track processing is disabled, WebRtcLocalAudioTrackAdapter
150  // is used to pass the channel ids to WebRtcAudioDeviceImpl, the data flow
151  // becomes WebRtcAudioDeviceImpl ==> WebRTC.
152  // TODO(xians): Only return NULL after the APM in WebRTC is deprecated.
153  // See See http://crbug/365672 for details.
154  return MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled()?
155      NULL : this;
156}
157
158}  // namespace content
159