blob: de86a3c4cc36e5d381a4c419cb6dd76409d9bcd2 [file] [log] [blame]
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001// Copyright (c) 2012 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_local_audio_track.h"
6
7#include "content/renderer/media/webrtc_audio_capturer.h"
8#include "content/renderer/media/webrtc_audio_capturer_sink_owner.h"
Ben Murdocheb525c52013-07-10 11:40:50 +01009#include "third_party/libjingle/source/talk/media/base/audiorenderer.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010010
11namespace content {
12
13static const char kAudioTrackKind[] = "audio";
14
15scoped_refptr<WebRtcLocalAudioTrack> WebRtcLocalAudioTrack::Create(
16 const std::string& id,
17 const scoped_refptr<WebRtcAudioCapturer>& capturer,
18 webrtc::AudioSourceInterface* track_source) {
19 talk_base::RefCountedObject<WebRtcLocalAudioTrack>* track =
20 new talk_base::RefCountedObject<WebRtcLocalAudioTrack>(
21 id, capturer, track_source);
22 return track;
23}
24
25WebRtcLocalAudioTrack::WebRtcLocalAudioTrack(
26 const std::string& label,
27 const scoped_refptr<WebRtcAudioCapturer>& capturer,
28 webrtc::AudioSourceInterface* track_source)
29 : webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(label),
30 capturer_(capturer),
Ben Murdochbb1529c2013-08-08 10:24:53 +010031 track_source_(track_source),
32 need_audio_processing_(!capturer->device_id().empty()) {
33 // The capturer with a valid device id is using microphone as source,
34 // and APM (AudioProcessingModule) is turned on only for microphone data.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010035 DCHECK(capturer.get());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010036 DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()";
37}
38
39WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() {
40 DCHECK(thread_checker_.CalledOnValidThread());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010041 DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()";
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010042 // Users might not call Stop() on the track.
Ben Murdochbb1529c2013-08-08 10:24:53 +010043 Stop();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010044}
45
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010046void WebRtcLocalAudioTrack::CaptureData(const int16* audio_data,
47 int number_of_channels,
48 int number_of_frames,
49 int audio_delay_milliseconds,
Ben Murdochbb1529c2013-08-08 10:24:53 +010050 int volume) {
51 scoped_refptr<WebRtcAudioCapturer> capturer;
52 std::vector<int> voe_channels;
53 int sample_rate = 0;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010054 SinkList sinks;
55 {
56 base::AutoLock auto_lock(lock_);
57 // When the track is diabled, we simply return here.
58 // TODO(xians): Figure out if we should feed zero to sinks instead, in
59 // order to inject VAD data in such case.
60 if (!enabled())
61 return;
62
Ben Murdochbb1529c2013-08-08 10:24:53 +010063 capturer = capturer_;
64 voe_channels = voe_channels_;
65 sample_rate = params_.sample_rate(),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010066 sinks = sinks_;
67 }
68
69 // Feed the data to the sinks.
Ben Murdochbb1529c2013-08-08 10:24:53 +010070 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) {
71 int new_volume = (*it)->CaptureData(voe_channels, audio_data, sample_rate,
72 number_of_channels, number_of_frames,
73 audio_delay_milliseconds, volume,
74 need_audio_processing_);
75 if (new_volume != 0 && capturer.get())
76 capturer->SetVolume(new_volume);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010077 }
78}
79
80void WebRtcLocalAudioTrack::SetCaptureFormat(
81 const media::AudioParameters& params) {
82 base::AutoLock auto_lock(lock_);
83 params_ = params;
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010084
85 // Update all the existing sinks with the new format.
86 for (SinkList::const_iterator it = sinks_.begin();
87 it != sinks_.end(); ++it)
88 (*it)->SetCaptureFormat(params);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010089}
90
Ben Murdochbb1529c2013-08-08 10:24:53 +010091void WebRtcLocalAudioTrack::AddChannel(int channel_id) {
92 DVLOG(1) << "WebRtcLocalAudioTrack::AddChannel(channel_id="
93 << channel_id << ")";
94 base::AutoLock auto_lock(lock_);
95 if (std::find(voe_channels_.begin(), voe_channels_.end(), channel_id) !=
96 voe_channels_.end()) {
97 // We need to handle the case when the same channel is connected to the
98 // track more than once.
99 return;
100 }
101
102 voe_channels_.push_back(channel_id);
103}
104
105void WebRtcLocalAudioTrack::RemoveChannel(int channel_id) {
106 DVLOG(1) << "WebRtcLocalAudioTrack::RemoveChannel(channel_id="
107 << channel_id << ")";
108 base::AutoLock auto_lock(lock_);
109 std::vector<int>::iterator iter =
110 std::find(voe_channels_.begin(), voe_channels_.end(), channel_id);
111 DCHECK(iter != voe_channels_.end());
112 voe_channels_.erase(iter);
113}
114
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100115// webrtc::AudioTrackInterface implementation.
116webrtc::AudioSourceInterface* WebRtcLocalAudioTrack::GetSource() const {
117 return track_source_;
118}
119
Ben Murdochbb1529c2013-08-08 10:24:53 +0100120cricket::AudioRenderer* WebRtcLocalAudioTrack::GetRenderer() {
121 return this;
122}
123
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100124std::string WebRtcLocalAudioTrack::kind() const {
125 return kAudioTrackKind;
126}
127
128void WebRtcLocalAudioTrack::AddSink(WebRtcAudioCapturerSink* sink) {
129 DCHECK(thread_checker_.CalledOnValidThread());
130 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()";
131 base::AutoLock auto_lock(lock_);
132 sink->SetCaptureFormat(params_);
133
134 // Verify that |sink| is not already added to the list.
135 DCHECK(std::find_if(
136 sinks_.begin(), sinks_.end(),
137 WebRtcAudioCapturerSinkOwner::WrapsSink(sink)) == sinks_.end());
138
139 // Create (and add to the list) a new WebRtcAudioCapturerSinkOwner which owns
140 // the |sink| and delagates all calls to the WebRtcAudioCapturerSink
141 // interface.
142 sinks_.push_back(new WebRtcAudioCapturerSinkOwner(sink));
143}
144
145void WebRtcLocalAudioTrack::RemoveSink(
146 WebRtcAudioCapturerSink* sink) {
147 DCHECK(thread_checker_.CalledOnValidThread());
148 DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()";
149
150 base::AutoLock auto_lock(lock_);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100151 // Get iterator to the first element for which WrapsSink(sink) returns true.
152 SinkList::iterator it = std::find_if(
153 sinks_.begin(), sinks_.end(),
154 WebRtcAudioCapturerSinkOwner::WrapsSink(sink));
155 if (it != sinks_.end()) {
156 // Clear the delegate to ensure that no more capture callbacks will
157 // be sent to this sink. Also avoids a possible crash which can happen
158 // if this method is called while capturing is active.
159 (*it)->Reset();
160 sinks_.erase(it);
161 }
162}
163
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100164void WebRtcLocalAudioTrack::Start() {
165 DCHECK(thread_checker_.CalledOnValidThread());
166 DVLOG(1) << "WebRtcLocalAudioTrack::Start()";
167 if (capturer_.get())
Ben Murdochbb1529c2013-08-08 10:24:53 +0100168 capturer_->AddTrack(this);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100169}
170
171void WebRtcLocalAudioTrack::Stop() {
172 DCHECK(thread_checker_.CalledOnValidThread());
173 DVLOG(1) << "WebRtcLocalAudioTrack::Stop()";
Ben Murdochbb1529c2013-08-08 10:24:53 +0100174 if (!capturer_.get())
175 return;
176
177 capturer_->RemoveTrack(this);
178
179 // Protect the pointers using the lock when accessing |sinks_| and
180 // setting the |capturer_| to NULL.
181 SinkList sinks;
182 {
183 base::AutoLock auto_lock(lock_);
184 sinks = sinks_;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100185 capturer_ = NULL;
186 }
Ben Murdochbb1529c2013-08-08 10:24:53 +0100187
188 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it)
189 (*it)->Reset();
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100190}
191
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100192} // namespace content