Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: content/renderer/media/webaudio_capturer_source.cc

Issue 1714593003: Introduce media::AudioPushFifo and a couple of use cases (and clean-ups). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix Win compile issue. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/media/webaudio_capturer_source.h" 5 #include "content/renderer/media/webaudio_capturer_source.h"
6 6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
7 #include "base/logging.h" 9 #include "base/logging.h"
8 #include "base/time/time.h" 10 #include "base/time/time.h"
9 #include "content/renderer/media/webrtc_local_audio_track.h" 11 #include "content/renderer/media/webrtc_local_audio_track.h"
10 12
11 using media::AudioBus; 13 using media::AudioBus;
12 using media::AudioFifo;
13 using media::AudioParameters; 14 using media::AudioParameters;
14 using media::ChannelLayout; 15 using media::ChannelLayout;
15 using media::CHANNEL_LAYOUT_MONO; 16 using media::CHANNEL_LAYOUT_MONO;
16 using media::CHANNEL_LAYOUT_STEREO; 17 using media::CHANNEL_LAYOUT_STEREO;
17 18
18 static const int kMaxNumberOfBuffersInFifo = 5;
19
20 namespace content { 19 namespace content {
21 20
22 WebAudioCapturerSource::WebAudioCapturerSource( 21 WebAudioCapturerSource::WebAudioCapturerSource(
23 const blink::WebMediaStreamSource& blink_source) 22 const blink::WebMediaStreamSource& blink_source)
24 : track_(NULL), 23 : track_(NULL),
25 audio_format_changed_(false), 24 audio_format_changed_(false),
26 blink_source_(blink_source) { 25 rechunker_(base::TimeDelta::FromMilliseconds(10),
27 } 26 base::Bind(&WebAudioCapturerSource::DeliverRechunkedAudio,
27 base::Unretained(this))),
28 blink_source_(blink_source) {}
28 29
29 WebAudioCapturerSource::~WebAudioCapturerSource() { 30 WebAudioCapturerSource::~WebAudioCapturerSource() {
30 DCHECK(thread_checker_.CalledOnValidThread()); 31 DCHECK(thread_checker_.CalledOnValidThread());
31 removeFromBlinkSource(); 32 removeFromBlinkSource();
32 } 33 }
33 34
34 void WebAudioCapturerSource::setFormat( 35 void WebAudioCapturerSource::setFormat(
35 size_t number_of_channels, float sample_rate) { 36 size_t number_of_channels, float sample_rate) {
36 DCHECK(thread_checker_.CalledOnValidThread()); 37 DCHECK(thread_checker_.CalledOnValidThread());
37 DVLOG(1) << "WebAudioCapturerSource::setFormat(sample_rate=" 38 DVLOG(1) << "WebAudioCapturerSource::setFormat(sample_rate="
38 << sample_rate << ")"; 39 << sample_rate << ")";
39 40
40 // If the channel count is greater than 8, use discrete layout. However, 41 // If the channel count is greater than 8, use discrete layout. However,
41 // anything beyond 8 is ignored by the subsequent (WebRTC) audio pipeline. 42 // anything beyond 8 is ignored by the subsequent (WebRTC) audio pipeline.
42 ChannelLayout channel_layout = 43 ChannelLayout channel_layout =
43 number_of_channels > 8 ? media::CHANNEL_LAYOUT_DISCRETE 44 number_of_channels > 8 ? media::CHANNEL_LAYOUT_DISCRETE
44 : media::GuessChannelLayout(number_of_channels); 45 : media::GuessChannelLayout(number_of_channels);
45 46
46 base::AutoLock auto_lock(lock_); 47 base::AutoLock auto_lock(lock_);
47 48
48 // Set the format used by this WebAudioCapturerSource. We are using 10ms data 49 // Set the format used by this WebAudioCapturerSource. We are using 10ms data
49 // as buffer size since that is the native buffer size of WebRtc packet 50 // as buffer size since that is the native buffer size of WebRtc packet
50 // running on. 51 // running on.
52 rechunker_.SetSampleRate(sample_rate);
51 params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 53 params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
52 sample_rate, 16, sample_rate / 100); 54 sample_rate, 16, rechunker_.output_frames());
53 55
54 // Take care of the discrete channel layout case. 56 // Take care of the discrete channel layout case.
55 params_.set_channels_for_discrete(number_of_channels); 57 params_.set_channels_for_discrete(number_of_channels);
56 58
57 audio_format_changed_ = true; 59 audio_format_changed_ = true;
58 60
59 wrapper_bus_ = AudioBus::CreateWrapper(params_.channels()); 61 if (!wrapper_bus_ ||
60 capture_bus_ = AudioBus::Create(params_); 62 wrapper_bus_->channels() != static_cast<int>(number_of_channels)) {
61 63 wrapper_bus_ = AudioBus::CreateWrapper(params_.channels());
62 fifo_.reset(new AudioFifo( 64 }
63 params_.channels(),
64 kMaxNumberOfBuffersInFifo * params_.frames_per_buffer()));
65 } 65 }
66 66
67 void WebAudioCapturerSource::Start(WebRtcLocalAudioTrack* track) { 67 void WebAudioCapturerSource::Start(WebRtcLocalAudioTrack* track) {
68 DCHECK(thread_checker_.CalledOnValidThread()); 68 DCHECK(thread_checker_.CalledOnValidThread());
69 DCHECK(track); 69 DCHECK(track);
70 base::AutoLock auto_lock(lock_); 70 base::AutoLock auto_lock(lock_);
71 track_ = track; 71 track_ = track;
72 } 72 }
73 73
74 void WebAudioCapturerSource::Stop() { 74 void WebAudioCapturerSource::Stop() {
75 DCHECK(thread_checker_.CalledOnValidThread()); 75 DCHECK(thread_checker_.CalledOnValidThread());
76 { 76 {
77 base::AutoLock auto_lock(lock_); 77 base::AutoLock auto_lock(lock_);
78 track_ = NULL; 78 track_ = NULL;
79 } 79 }
80 // removeFromBlinkSource() should not be called while |lock_| is acquired, 80 // removeFromBlinkSource() should not be called while |lock_| is acquired,
81 // as it could result in a deadlock. 81 // as it could result in a deadlock.
82 removeFromBlinkSource(); 82 removeFromBlinkSource();
83 } 83 }
84 84
85 void WebAudioCapturerSource::consumeAudio( 85 void WebAudioCapturerSource::consumeAudio(
86 const blink::WebVector<const float*>& audio_data, 86 const blink::WebVector<const float*>& audio_data,
87 size_t number_of_frames) { 87 size_t number_of_frames) {
88 // TODO(miu): Plumbing is needed to determine the actual capture timestamp
89 // of the audio, instead of just snapshotting TimeTicks::Now(), for proper
90 // audio/video sync. http://crbug.com/335335
91 base::TimeTicks reference_time = base::TimeTicks::Now();
92
88 base::AutoLock auto_lock(lock_); 93 base::AutoLock auto_lock(lock_);
89 if (!track_) 94 if (!track_)
90 return; 95 return;
91 96
92 // Update the downstream client if the audio format has been changed. 97 // Update the downstream client if the audio format has been changed.
93 if (audio_format_changed_) { 98 if (audio_format_changed_) {
94 track_->OnSetFormat(params_); 99 track_->OnSetFormat(params_);
95 audio_format_changed_ = false; 100 audio_format_changed_ = false;
96 } 101 }
97 102
98 wrapper_bus_->set_frames(number_of_frames); 103 wrapper_bus_->set_frames(number_of_frames);
99
100 // Make sure WebKit is honoring what it told us up front
101 // about the channels.
102 DCHECK_EQ(params_.channels(), static_cast<int>(audio_data.size())); 104 DCHECK_EQ(params_.channels(), static_cast<int>(audio_data.size()));
103
104 for (size_t i = 0; i < audio_data.size(); ++i) 105 for (size_t i = 0; i < audio_data.size(); ++i)
105 wrapper_bus_->SetChannelData(i, const_cast<float*>(audio_data[i])); 106 wrapper_bus_->SetChannelData(i, const_cast<float*>(audio_data[i]));
106 107
107 // Handle mismatch between WebAudio buffer-size and WebRTC. 108 // The following will result in zero, one, or multiple synchronous calls to
108 int available = fifo_->max_frames() - fifo_->frames(); 109 // DeliverRechunkedAudio().
109 if (available < static_cast<int>(number_of_frames)) { 110 rechunker_.Push(*wrapper_bus_, reference_time - base::TimeTicks());
o1ka 2016/02/22 13:04:47 I like how neat it becomes!
miu 2016/02/23 04:27:41 Acknowledged.
110 NOTREACHED() << "WebAudioCapturerSource::Consume() : FIFO overrun."; 111 }
111 return;
112 }
113 112
114 // Compute the estimated capture time of the first sample frame of audio that 113 void WebAudioCapturerSource::DeliverRechunkedAudio(
115 // will be consumed from the FIFO in the loop below. 114 const media::AudioBus& audio_bus,
116 base::TimeTicks estimated_capture_time = base::TimeTicks::Now() - 115 base::TimeDelta reference_timestamp) {
117 fifo_->frames() * base::TimeDelta::FromSeconds(1) / params_.sample_rate(); 116 lock_.AssertAcquired();
118 117 track_->Capture(audio_bus, base::TimeTicks() + reference_timestamp, false);
119 fifo_->Push(wrapper_bus_.get());
120 while (fifo_->frames() >= capture_bus_->frames()) {
121 fifo_->Consume(capture_bus_.get(), 0, capture_bus_->frames());
122 track_->Capture(*capture_bus_, estimated_capture_time, false);
123
124 // Advance the estimated capture time for the next FIFO consume operation.
125 estimated_capture_time +=
126 capture_bus_->frames() * base::TimeDelta::FromSeconds(1) /
127 params_.sample_rate();
128 }
129 } 118 }
130 119
131 // If registered as audio consumer in |blink_source_|, deregister from 120 // If registered as audio consumer in |blink_source_|, deregister from
132 // |blink_source_| and stop keeping a reference to |blink_source_|. 121 // |blink_source_| and stop keeping a reference to |blink_source_|.
133 // Failure to call this method when stopping the track might leave an invalid 122 // Failure to call this method when stopping the track might leave an invalid
134 // WebAudioCapturerSource reference still registered as an audio consumer on 123 // WebAudioCapturerSource reference still registered as an audio consumer on
135 // the blink side. 124 // the blink side.
136 void WebAudioCapturerSource::removeFromBlinkSource() { 125 void WebAudioCapturerSource::removeFromBlinkSource() {
137 if (!blink_source_.isNull()) { 126 if (!blink_source_.isNull()) {
138 blink_source_.removeAudioConsumer(this); 127 blink_source_.removeAudioConsumer(this);
139 blink_source_.reset(); 128 blink_source_.reset();
140 } 129 }
141 } 130 }
142 131
143 } // namespace content 132 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698