OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/renderer/media/webaudio_media_stream_source.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/logging.h" | |
10 | |
11 namespace content { | |
12 | |
13 WebAudioMediaStreamSource::WebAudioMediaStreamSource( | |
14 blink::WebMediaStreamSource* blink_source) | |
15 : MediaStreamAudioSource(false /* is_remote */), | |
16 is_registered_consumer_(false), | |
17 fifo_(base::Bind(&WebAudioMediaStreamSource::DeliverRebufferedAudio, | |
18 base::Unretained(this))), | |
19 blink_source_(*blink_source) { | |
20 DVLOG(1) << "WebAudioMediaStreamSource::WebAudioMediaStreamSource()"; | |
21 } | |
22 | |
23 WebAudioMediaStreamSource::~WebAudioMediaStreamSource() { | |
24 DVLOG(1) << "WebAudioMediaStreamSource::~WebAudioMediaStreamSource()"; | |
25 EnsureSourceIsStopped(); | |
26 } | |
27 | |
28 void WebAudioMediaStreamSource::setFormat(size_t number_of_channels, | |
29 float sample_rate) { | |
30 DCHECK(thread_checker_.CalledOnValidThread()); | |
31 VLOG(1) << "WebAudio media stream source changed format to: channels=" | |
32 << number_of_channels << ", sample_rate=" << sample_rate; | |
33 | |
34 // If the channel count is greater than 8, use discrete layout. However, | |
35 // anything beyond 8 is ignored by some audio tracks/sinks. | |
36 media::ChannelLayout channel_layout = | |
37 number_of_channels > 8 ? media::CHANNEL_LAYOUT_DISCRETE | |
38 : media::GuessChannelLayout(number_of_channels); | |
39 | |
40 // Set the format used by this WebAudioMediaStreamSource. We are using 10ms | |
41 // data as a buffer size since that is the native buffer size of WebRtc packet | |
42 // running on. | |
43 // | |
44 // TODO(miu): Re-evaluate whether this is needed. For now (this refactoring), | |
45 // I did not want to change behavior. http://crbug.com/577874 | |
46 fifo_.Reset(sample_rate / 100); | |
47 media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | |
48 channel_layout, sample_rate, 16, | |
49 fifo_.frames_per_buffer()); | |
50 // Take care of the discrete channel layout case. | |
51 params.set_channels_for_discrete(number_of_channels); | |
52 MediaStreamAudioSource::SetFormat(params); | |
53 | |
54 if (!wrapper_bus_ || wrapper_bus_->channels() != params.channels()) | |
55 wrapper_bus_ = media::AudioBus::CreateWrapper(params.channels()); | |
56 } | |
57 | |
58 bool WebAudioMediaStreamSource::EnsureSourceIsStarted() { | |
59 DCHECK(thread_checker_.CalledOnValidThread()); | |
60 if (is_registered_consumer_) | |
61 return true; | |
62 if (blink_source_.isNull() || !blink_source_.requiresAudioConsumer()) | |
63 return false; | |
64 VLOG(1) << "Starting WebAudio media stream source."; | |
65 blink_source_.addAudioConsumer(this); | |
66 is_registered_consumer_ = true; | |
67 return true; | |
68 } | |
69 | |
70 void WebAudioMediaStreamSource::EnsureSourceIsStopped() { | |
71 DCHECK(thread_checker_.CalledOnValidThread()); | |
72 if (!is_registered_consumer_) | |
73 return; | |
74 is_registered_consumer_ = false; | |
75 DCHECK(!blink_source_.isNull()); | |
76 blink_source_.removeAudioConsumer(this); | |
77 blink_source_.reset(); | |
78 VLOG(1) << "Stopped WebAudio media stream source. Final audio parameters={" | |
79 << GetAudioParameters().AsHumanReadableString() << "}."; | |
80 } | |
81 | |
82 void WebAudioMediaStreamSource::consumeAudio( | |
83 const blink::WebVector<const float*>& audio_data, | |
84 size_t number_of_frames) { | |
85 // TODO(miu): Plumbing is needed to determine the actual capture timestamp | |
86 // of the audio, instead of just snapshotting TimeTicks::Now(), for proper | |
87 // audio/video sync. http://crbug.com/335335 | |
88 current_reference_time_ = base::TimeTicks::Now(); | |
89 | |
90 wrapper_bus_->set_frames(number_of_frames); | |
91 DCHECK_EQ(wrapper_bus_->channels(), static_cast<int>(audio_data.size())); | |
92 for (size_t i = 0; i < audio_data.size(); ++i) | |
93 wrapper_bus_->SetChannelData(i, const_cast<float*>(audio_data[i])); | |
94 | |
95 // The following will result in zero, one, or multiple synchronous calls to | |
96 // DeliverRebufferedAudio(). | |
97 fifo_.Push(*wrapper_bus_); | |
98 } | |
99 | |
100 void WebAudioMediaStreamSource::DeliverRebufferedAudio( | |
101 const media::AudioBus& audio_bus, | |
102 int frame_delay) { | |
103 const base::TimeTicks reference_time = | |
104 current_reference_time_ + | |
105 base::TimeDelta::FromMicroseconds( | |
106 frame_delay * base::Time::kMicrosecondsPerSecond / | |
107 MediaStreamAudioSource::GetAudioParameters().sample_rate()); | |
108 MediaStreamAudioSource::DeliverDataToTracks(audio_bus, reference_time); | |
109 } | |
110 | |
111 } // namespace content | |
OLD | NEW |