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/render_audiosourceprovider.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/basictypes.h" | |
10 #include "base/command_line.h" | |
11 #include "base/logging.h" | |
12 #include "content/renderer/media/audio_device_factory.h" | |
13 #include "content/renderer/media/audio_renderer_mixer_manager.h" | |
14 #include "content/renderer/media/renderer_audio_output_device.h" | |
15 #include "content/renderer/render_thread_impl.h" | |
16 #include "media/base/audio_renderer_mixer_input.h" | |
17 #include "media/base/media_switches.h" | |
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAudioSourceProvide
rClient.h" | |
19 | |
20 using std::vector; | |
21 using WebKit::WebVector; | |
22 | |
23 namespace content { | |
24 | |
25 RenderAudioSourceProvider::RenderAudioSourceProvider(int source_render_view_id) | |
26 : is_initialized_(false), | |
27 channels_(0), | |
28 sample_rate_(0), | |
29 is_running_(false), | |
30 renderer_(NULL), | |
31 client_(NULL) { | |
32 // We create an AudioRendererSink here, but we don't yet know the audio format | |
33 // (sample-rate, etc.) at this point. Later, when Initialize() is called, we | |
34 // have the audio format information and call AudioRendererSink::Initialize() | |
35 // to fully initialize it. | |
36 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); | |
37 #if defined(OS_WIN) || defined(OS_MACOSX) | |
38 const bool use_mixing = | |
39 !cmd_line->HasSwitch(switches::kDisableRendererSideMixing); | |
40 #else | |
41 const bool use_mixing = | |
42 cmd_line->HasSwitch(switches::kEnableRendererSideMixing); | |
43 #endif | |
44 | |
45 if (use_mixing) { | |
46 default_sink_ = RenderThreadImpl::current()-> | |
47 GetAudioRendererMixerManager()->CreateInput(source_render_view_id); | |
48 DVLOG(1) << "Using AudioRendererMixerManager-provided sink: " | |
49 << default_sink_.get(); | |
50 } else { | |
51 scoped_refptr<RendererAudioOutputDevice> device = | |
52 AudioDeviceFactory::NewOutputDevice(); | |
53 // The RenderView creating RenderAudioSourceProvider will be the source of | |
54 // the audio (WebMediaPlayer is always associated with a document in a frame | |
55 // at the time RenderAudioSourceProvider is instantiated). | |
56 device->SetSourceRenderView(source_render_view_id); | |
57 default_sink_ = device; | |
58 DVLOG(1) << "Using AudioDeviceFactory-provided sink: " | |
59 << default_sink_.get(); | |
60 } | |
61 } | |
62 | |
63 void RenderAudioSourceProvider::setClient( | |
64 WebKit::WebAudioSourceProviderClient* client) { | |
65 // Synchronize with other uses of client_ and default_sink_. | |
66 base::AutoLock auto_lock(sink_lock_); | |
67 | |
68 if (client && client != client_) { | |
69 // Detach the audio renderer from normal playback. | |
70 default_sink_->Stop(); | |
71 | |
72 // The client will now take control by calling provideInput() periodically. | |
73 client_ = client; | |
74 | |
75 if (is_initialized_) { | |
76 // The client needs to be notified of the audio format, if available. | |
77 // If the format is not yet available, we'll be notified later | |
78 // when Initialize() is called. | |
79 | |
80 // Inform WebKit about the audio stream format. | |
81 client->setFormat(channels_, sample_rate_); | |
82 } | |
83 } else if (!client && client_) { | |
84 // Restore normal playback. | |
85 client_ = NULL; | |
86 // TODO(crogers): We should call default_sink_->Play() if we're | |
87 // in the playing state. | |
88 } | |
89 } | |
90 | |
91 void RenderAudioSourceProvider::provideInput( | |
92 const WebVector<float*>& audio_data, size_t number_of_frames) { | |
93 DCHECK(client_); | |
94 | |
95 if (renderer_ && is_initialized_ && is_running_) { | |
96 // Wrap WebVector as std::vector. | |
97 vector<float*> v(audio_data.size()); | |
98 for (size_t i = 0; i < audio_data.size(); ++i) | |
99 v[i] = audio_data[i]; | |
100 | |
101 scoped_ptr<media::AudioBus> audio_bus = media::AudioBus::WrapVector( | |
102 number_of_frames, v); | |
103 | |
104 // TODO(crogers): figure out if we should volume scale here or in common | |
105 // WebAudio code. In any case we need to take care of volume. | |
106 renderer_->Render(audio_bus.get(), 0); | |
107 } else { | |
108 // Provide silence if the source is not running. | |
109 for (size_t i = 0; i < audio_data.size(); ++i) | |
110 memset(audio_data[i], 0, sizeof(*audio_data[0]) * number_of_frames); | |
111 } | |
112 } | |
113 | |
114 void RenderAudioSourceProvider::Start() { | |
115 base::AutoLock auto_lock(sink_lock_); | |
116 if (!client_) | |
117 default_sink_->Start(); | |
118 is_running_ = true; | |
119 } | |
120 | |
121 void RenderAudioSourceProvider::Stop() { | |
122 base::AutoLock auto_lock(sink_lock_); | |
123 if (!client_) | |
124 default_sink_->Stop(); | |
125 is_running_ = false; | |
126 } | |
127 | |
128 void RenderAudioSourceProvider::Play() { | |
129 base::AutoLock auto_lock(sink_lock_); | |
130 if (!client_) | |
131 default_sink_->Play(); | |
132 is_running_ = true; | |
133 } | |
134 | |
135 void RenderAudioSourceProvider::Pause(bool flush) { | |
136 base::AutoLock auto_lock(sink_lock_); | |
137 if (!client_) | |
138 default_sink_->Pause(flush); | |
139 is_running_ = false; | |
140 } | |
141 | |
142 bool RenderAudioSourceProvider::SetVolume(double volume) { | |
143 base::AutoLock auto_lock(sink_lock_); | |
144 if (!client_) | |
145 default_sink_->SetVolume(volume); | |
146 return true; | |
147 } | |
148 | |
149 void RenderAudioSourceProvider::Initialize( | |
150 const media::AudioParameters& params, | |
151 RenderCallback* renderer) { | |
152 base::AutoLock auto_lock(sink_lock_); | |
153 CHECK(!is_initialized_); | |
154 renderer_ = renderer; | |
155 | |
156 default_sink_->Initialize(params, renderer); | |
157 | |
158 // Keep track of the format in case the client hasn't yet been set. | |
159 channels_ = params.channels(); | |
160 sample_rate_ = params.sample_rate(); | |
161 | |
162 if (client_) { | |
163 // Inform WebKit about the audio stream format. | |
164 client_->setFormat(channels_, sample_rate_); | |
165 } | |
166 | |
167 is_initialized_ = true; | |
168 } | |
169 | |
170 RenderAudioSourceProvider::~RenderAudioSourceProvider() {} | |
171 | |
172 } // namespace content | |
OLD | NEW |