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

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 unittest compile breakage caused by recent method rename. Created 4 years, 9 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
« no previous file with comments | « content/renderer/media/webaudio_capturer_source.h ('k') | media/base/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
9 #include "content/renderer/media/webrtc_local_audio_track.h" 10 #include "content/renderer/media/webrtc_local_audio_track.h"
10 11
11 using media::AudioBus; 12 using media::AudioBus;
12 using media::AudioFifo;
13 using media::AudioParameters; 13 using media::AudioParameters;
14 using media::ChannelLayout; 14 using media::ChannelLayout;
15 using media::CHANNEL_LAYOUT_MONO; 15 using media::CHANNEL_LAYOUT_MONO;
16 using media::CHANNEL_LAYOUT_STEREO; 16 using media::CHANNEL_LAYOUT_STEREO;
17 17
18 static const int kMaxNumberOfBuffersInFifo = 5;
19
20 namespace content { 18 namespace content {
21 19
22 WebAudioCapturerSource::WebAudioCapturerSource( 20 WebAudioCapturerSource::WebAudioCapturerSource(
23 const blink::WebMediaStreamSource& blink_source) 21 const blink::WebMediaStreamSource& blink_source)
24 : track_(NULL), 22 : track_(NULL),
25 audio_format_changed_(false), 23 audio_format_changed_(false),
26 blink_source_(blink_source) { 24 fifo_(base::Bind(&WebAudioCapturerSource::DeliverRebufferedAudio,
27 } 25 base::Unretained(this))),
26 blink_source_(blink_source) {}
28 27
29 WebAudioCapturerSource::~WebAudioCapturerSource() { 28 WebAudioCapturerSource::~WebAudioCapturerSource() {
30 DCHECK(thread_checker_.CalledOnValidThread()); 29 DCHECK(thread_checker_.CalledOnValidThread());
31 removeFromBlinkSource(); 30 removeFromBlinkSource();
32 } 31 }
33 32
34 void WebAudioCapturerSource::setFormat( 33 void WebAudioCapturerSource::setFormat(
35 size_t number_of_channels, float sample_rate) { 34 size_t number_of_channels, float sample_rate) {
36 DCHECK(thread_checker_.CalledOnValidThread()); 35 DCHECK(thread_checker_.CalledOnValidThread());
37 DVLOG(1) << "WebAudioCapturerSource::setFormat(sample_rate=" 36 DVLOG(1) << "WebAudioCapturerSource::setFormat(sample_rate="
38 << sample_rate << ")"; 37 << sample_rate << ")";
39 38
40 // If the channel count is greater than 8, use discrete layout. However, 39 // If the channel count is greater than 8, use discrete layout. However,
41 // anything beyond 8 is ignored by the subsequent (WebRTC) audio pipeline. 40 // anything beyond 8 is ignored by the subsequent (WebRTC) audio pipeline.
42 ChannelLayout channel_layout = 41 ChannelLayout channel_layout =
43 number_of_channels > 8 ? media::CHANNEL_LAYOUT_DISCRETE 42 number_of_channels > 8 ? media::CHANNEL_LAYOUT_DISCRETE
44 : media::GuessChannelLayout(number_of_channels); 43 : media::GuessChannelLayout(number_of_channels);
45 44
46 base::AutoLock auto_lock(lock_); 45 base::AutoLock auto_lock(lock_);
47 46
48 // Set the format used by this WebAudioCapturerSource. We are using 10ms data 47 // 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 48 // as buffer size since that is the native buffer size of WebRtc packet
50 // running on. 49 // running on.
50 fifo_.Reset(sample_rate / 100);
51 params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 51 params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
52 sample_rate, 16, sample_rate / 100); 52 sample_rate, 16, fifo_.frames_per_buffer());
53 53
54 // Take care of the discrete channel layout case. 54 // Take care of the discrete channel layout case.
55 params_.set_channels_for_discrete(number_of_channels); 55 params_.set_channels_for_discrete(number_of_channels);
56 56
57 audio_format_changed_ = true; 57 audio_format_changed_ = true;
58 58
59 wrapper_bus_ = AudioBus::CreateWrapper(params_.channels()); 59 if (!wrapper_bus_ ||
60 capture_bus_ = AudioBus::Create(params_); 60 wrapper_bus_->channels() != static_cast<int>(number_of_channels)) {
61 61 wrapper_bus_ = AudioBus::CreateWrapper(params_.channels());
62 fifo_.reset(new AudioFifo( 62 }
63 params_.channels(),
64 kMaxNumberOfBuffersInFifo * params_.frames_per_buffer()));
65 } 63 }
66 64
67 void WebAudioCapturerSource::Start(WebRtcLocalAudioTrack* track) { 65 void WebAudioCapturerSource::Start(WebRtcLocalAudioTrack* track) {
68 DCHECK(thread_checker_.CalledOnValidThread()); 66 DCHECK(thread_checker_.CalledOnValidThread());
69 DCHECK(track); 67 DCHECK(track);
70 base::AutoLock auto_lock(lock_); 68 base::AutoLock auto_lock(lock_);
71 track_ = track; 69 track_ = track;
72 } 70 }
73 71
74 void WebAudioCapturerSource::Stop() { 72 void WebAudioCapturerSource::Stop() {
75 DCHECK(thread_checker_.CalledOnValidThread()); 73 DCHECK(thread_checker_.CalledOnValidThread());
76 { 74 {
77 base::AutoLock auto_lock(lock_); 75 base::AutoLock auto_lock(lock_);
78 track_ = NULL; 76 track_ = NULL;
79 } 77 }
80 // removeFromBlinkSource() should not be called while |lock_| is acquired, 78 // removeFromBlinkSource() should not be called while |lock_| is acquired,
81 // as it could result in a deadlock. 79 // as it could result in a deadlock.
82 removeFromBlinkSource(); 80 removeFromBlinkSource();
83 } 81 }
84 82
85 void WebAudioCapturerSource::consumeAudio( 83 void WebAudioCapturerSource::consumeAudio(
86 const blink::WebVector<const float*>& audio_data, 84 const blink::WebVector<const float*>& audio_data,
87 size_t number_of_frames) { 85 size_t number_of_frames) {
86 // TODO(miu): Plumbing is needed to determine the actual capture timestamp
87 // of the audio, instead of just snapshotting TimeTicks::Now(), for proper
88 // audio/video sync. http://crbug.com/335335
89 current_reference_time_ = base::TimeTicks::Now();
90
88 base::AutoLock auto_lock(lock_); 91 base::AutoLock auto_lock(lock_);
89 if (!track_) 92 if (!track_)
90 return; 93 return;
91 94
92 // Update the downstream client if the audio format has been changed. 95 // Update the downstream client if the audio format has been changed.
93 if (audio_format_changed_) { 96 if (audio_format_changed_) {
94 track_->OnSetFormat(params_); 97 track_->OnSetFormat(params_);
95 audio_format_changed_ = false; 98 audio_format_changed_ = false;
96 } 99 }
97 100
98 wrapper_bus_->set_frames(number_of_frames); 101 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())); 102 DCHECK_EQ(params_.channels(), static_cast<int>(audio_data.size()));
103
104 for (size_t i = 0; i < audio_data.size(); ++i) 103 for (size_t i = 0; i < audio_data.size(); ++i)
105 wrapper_bus_->SetChannelData(i, const_cast<float*>(audio_data[i])); 104 wrapper_bus_->SetChannelData(i, const_cast<float*>(audio_data[i]));
106 105
107 // Handle mismatch between WebAudio buffer-size and WebRTC. 106 // The following will result in zero, one, or multiple synchronous calls to
108 int available = fifo_->max_frames() - fifo_->frames(); 107 // DeliverRebufferedAudio().
109 if (available < static_cast<int>(number_of_frames)) { 108 fifo_.Push(*wrapper_bus_);
110 NOTREACHED() << "WebAudioCapturerSource::Consume() : FIFO overrun."; 109 }
111 return;
112 }
113 110
114 // Compute the estimated capture time of the first sample frame of audio that 111 void WebAudioCapturerSource::DeliverRebufferedAudio(
115 // will be consumed from the FIFO in the loop below. 112 const media::AudioBus& audio_bus,
116 base::TimeTicks estimated_capture_time = base::TimeTicks::Now() - 113 int frame_delay) {
117 fifo_->frames() * base::TimeDelta::FromSeconds(1) / params_.sample_rate(); 114 lock_.AssertAcquired();
118 115 const base::TimeTicks reference_time =
119 fifo_->Push(wrapper_bus_.get()); 116 current_reference_time_ +
120 while (fifo_->frames() >= capture_bus_->frames()) { 117 base::TimeDelta::FromMicroseconds(frame_delay *
121 fifo_->Consume(capture_bus_.get(), 0, capture_bus_->frames()); 118 base::Time::kMicrosecondsPerSecond /
122 track_->Capture(*capture_bus_, estimated_capture_time, false); 119 params_.sample_rate());
123 120 track_->Capture(audio_bus, reference_time, false);
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 } 121 }
130 122
131 // If registered as audio consumer in |blink_source_|, deregister from 123 // If registered as audio consumer in |blink_source_|, deregister from
132 // |blink_source_| and stop keeping a reference to |blink_source_|. 124 // |blink_source_| and stop keeping a reference to |blink_source_|.
133 // Failure to call this method when stopping the track might leave an invalid 125 // Failure to call this method when stopping the track might leave an invalid
134 // WebAudioCapturerSource reference still registered as an audio consumer on 126 // WebAudioCapturerSource reference still registered as an audio consumer on
135 // the blink side. 127 // the blink side.
136 void WebAudioCapturerSource::removeFromBlinkSource() { 128 void WebAudioCapturerSource::removeFromBlinkSource() {
137 if (!blink_source_.isNull()) { 129 if (!blink_source_.isNull()) {
138 blink_source_.removeAudioConsumer(this); 130 blink_source_.removeAudioConsumer(this);
139 blink_source_.reset(); 131 blink_source_.reset();
140 } 132 }
141 } 133 }
142 134
143 } // namespace content 135 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/webaudio_capturer_source.h ('k') | media/base/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698