| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/webaudiosourceprovider_impl.h" | 5 #include "media/blink/webaudiosourceprovider_impl.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "media/base/bind_to_current_loop.h" | 12 #include "media/base/bind_to_current_loop.h" |
| 13 #include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h" | 13 #include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h" |
| 14 | 14 |
| 15 using blink::WebVector; | 15 using blink::WebVector; |
| 16 | 16 |
| 17 namespace content { | 17 namespace media { |
| 18 | 18 |
| 19 namespace { | 19 namespace { |
| 20 | 20 |
| 21 // Simple helper class for Try() locks. Lock is Try()'d on construction and | 21 // Simple helper class for Try() locks. Lock is Try()'d on construction and |
| 22 // must be checked via the locked() attribute. If acquisition was successful | 22 // must be checked via the locked() attribute. If acquisition was successful |
| 23 // the lock will be released upon destruction. | 23 // the lock will be released upon destruction. |
| 24 // TODO(dalecurtis): This should probably move to base/ if others start using | 24 // TODO(dalecurtis): This should probably move to base/ if others start using |
| 25 // this pattern. | 25 // this pattern. |
| 26 class AutoTryLock { | 26 class AutoTryLock { |
| 27 public: | 27 public: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 40 | 40 |
| 41 private: | 41 private: |
| 42 base::Lock& lock_; | 42 base::Lock& lock_; |
| 43 const bool acquired_; | 43 const bool acquired_; |
| 44 DISALLOW_COPY_AND_ASSIGN(AutoTryLock); | 44 DISALLOW_COPY_AND_ASSIGN(AutoTryLock); |
| 45 }; | 45 }; |
| 46 | 46 |
| 47 } // namespace | 47 } // namespace |
| 48 | 48 |
| 49 WebAudioSourceProviderImpl::WebAudioSourceProviderImpl( | 49 WebAudioSourceProviderImpl::WebAudioSourceProviderImpl( |
| 50 const scoped_refptr<media::AudioRendererSink>& sink) | 50 const scoped_refptr<AudioRendererSink>& sink) |
| 51 : channels_(0), | 51 : channels_(0), |
| 52 sample_rate_(0), | 52 sample_rate_(0), |
| 53 volume_(1.0), | 53 volume_(1.0), |
| 54 state_(kStopped), | 54 state_(kStopped), |
| 55 renderer_(NULL), | 55 renderer_(NULL), |
| 56 client_(NULL), | 56 client_(NULL), |
| 57 sink_(sink), | 57 sink_(sink), |
| 58 weak_factory_(this) {} | 58 weak_factory_(this) {} |
| 59 | 59 |
| 60 WebAudioSourceProviderImpl::~WebAudioSourceProviderImpl() { | 60 WebAudioSourceProviderImpl::~WebAudioSourceProviderImpl() { |
| 61 } | 61 } |
| 62 | 62 |
| 63 void WebAudioSourceProviderImpl::setClient( | 63 void WebAudioSourceProviderImpl::setClient( |
| 64 blink::WebAudioSourceProviderClient* client) { | 64 blink::WebAudioSourceProviderClient* client) { |
| 65 base::AutoLock auto_lock(sink_lock_); | 65 base::AutoLock auto_lock(sink_lock_); |
| 66 if (client && client != client_) { | 66 if (client && client != client_) { |
| 67 // Detach the audio renderer from normal playback. | 67 // Detach the audio renderer from normal playback. |
| 68 sink_->Stop(); | 68 sink_->Stop(); |
| 69 | 69 |
| 70 // The client will now take control by calling provideInput() periodically. | 70 // The client will now take control by calling provideInput() periodically. |
| 71 client_ = client; | 71 client_ = client; |
| 72 | 72 |
| 73 set_format_cb_ = media::BindToCurrentLoop(base::Bind( | 73 set_format_cb_ = BindToCurrentLoop(base::Bind( |
| 74 &WebAudioSourceProviderImpl::OnSetFormat, weak_factory_.GetWeakPtr())); | 74 &WebAudioSourceProviderImpl::OnSetFormat, weak_factory_.GetWeakPtr())); |
| 75 | 75 |
| 76 // If |renderer_| is set, then run |set_format_cb_| to send |client_| | 76 // If |renderer_| is set, then run |set_format_cb_| to send |client_| |
| 77 // the current format info. If |renderer_| is not set, then |set_format_cb_| | 77 // the current format info. If |renderer_| is not set, then |set_format_cb_| |
| 78 // will get called when Initialize() is called. | 78 // will get called when Initialize() is called. |
| 79 // Note: Always using |set_format_cb_| ensures we have the same | 79 // Note: Always using |set_format_cb_| ensures we have the same |
| 80 // locking order when calling into |client_|. | 80 // locking order when calling into |client_|. |
| 81 if (renderer_) | 81 if (renderer_) |
| 82 base::ResetAndReturn(&set_format_cb_).Run(); | 82 base::ResetAndReturn(&set_format_cb_).Run(); |
| 83 } else if (!client && client_) { | 83 } else if (!client && client_) { |
| 84 // Restore normal playback. | 84 // Restore normal playback. |
| 85 client_ = NULL; | 85 client_ = NULL; |
| 86 sink_->SetVolume(volume_); | 86 sink_->SetVolume(volume_); |
| 87 if (state_ >= kStarted) | 87 if (state_ >= kStarted) |
| 88 sink_->Start(); | 88 sink_->Start(); |
| 89 if (state_ >= kPlaying) | 89 if (state_ >= kPlaying) |
| 90 sink_->Play(); | 90 sink_->Play(); |
| 91 } | 91 } |
| 92 } | 92 } |
| 93 | 93 |
| 94 void WebAudioSourceProviderImpl::provideInput( | 94 void WebAudioSourceProviderImpl::provideInput( |
| 95 const WebVector<float*>& audio_data, size_t number_of_frames) { | 95 const WebVector<float*>& audio_data, size_t number_of_frames) { |
| 96 if (!bus_wrapper_ || | 96 if (!bus_wrapper_ || |
| 97 static_cast<size_t>(bus_wrapper_->channels()) != audio_data.size()) { | 97 static_cast<size_t>(bus_wrapper_->channels()) != audio_data.size()) { |
| 98 bus_wrapper_ = media::AudioBus::CreateWrapper(audio_data.size()); | 98 bus_wrapper_ = AudioBus::CreateWrapper(static_cast<int>(audio_data.size())); |
| 99 } | 99 } |
| 100 | 100 |
| 101 bus_wrapper_->set_frames(number_of_frames); | 101 bus_wrapper_->set_frames(static_cast<int>(number_of_frames)); |
| 102 for (size_t i = 0; i < audio_data.size(); ++i) | 102 for (size_t i = 0; i < audio_data.size(); ++i) |
| 103 bus_wrapper_->SetChannelData(i, audio_data[i]); | 103 bus_wrapper_->SetChannelData(static_cast<int>(i), audio_data[i]); |
| 104 | 104 |
| 105 // Use a try lock to avoid contention in the real-time audio thread. | 105 // Use a try lock to avoid contention in the real-time audio thread. |
| 106 AutoTryLock auto_try_lock(sink_lock_); | 106 AutoTryLock auto_try_lock(sink_lock_); |
| 107 if (!auto_try_lock.locked() || state_ != kPlaying) { | 107 if (!auto_try_lock.locked() || state_ != kPlaying) { |
| 108 // Provide silence if we failed to acquire the lock or the source is not | 108 // Provide silence if we failed to acquire the lock or the source is not |
| 109 // running. | 109 // running. |
| 110 bus_wrapper_->Zero(); | 110 bus_wrapper_->Zero(); |
| 111 return; | 111 return; |
| 112 } | 112 } |
| 113 | 113 |
| 114 DCHECK(renderer_); | 114 DCHECK(renderer_); |
| 115 DCHECK(client_); | 115 DCHECK(client_); |
| 116 DCHECK_EQ(channels_, bus_wrapper_->channels()); | 116 DCHECK_EQ(channels_, bus_wrapper_->channels()); |
| 117 const size_t frames = renderer_->Render(bus_wrapper_.get(), 0); | 117 const int frames = renderer_->Render(bus_wrapper_.get(), 0); |
| 118 if (frames < number_of_frames) | 118 if (frames < static_cast<int>(number_of_frames)) { |
| 119 bus_wrapper_->ZeroFramesPartial(frames, number_of_frames - frames); | 119 bus_wrapper_->ZeroFramesPartial( |
| 120 frames, |
| 121 static_cast<int>(number_of_frames - frames)); |
| 122 } |
| 123 |
| 120 bus_wrapper_->Scale(volume_); | 124 bus_wrapper_->Scale(volume_); |
| 121 } | 125 } |
| 122 | 126 |
| 123 void WebAudioSourceProviderImpl::Start() { | 127 void WebAudioSourceProviderImpl::Start() { |
| 124 base::AutoLock auto_lock(sink_lock_); | 128 base::AutoLock auto_lock(sink_lock_); |
| 125 DCHECK_EQ(state_, kStopped); | 129 DCHECK_EQ(state_, kStopped); |
| 126 state_ = kStarted; | 130 state_ = kStarted; |
| 127 if (!client_) | 131 if (!client_) |
| 128 sink_->Start(); | 132 sink_->Start(); |
| 129 } | 133 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 153 | 157 |
| 154 bool WebAudioSourceProviderImpl::SetVolume(double volume) { | 158 bool WebAudioSourceProviderImpl::SetVolume(double volume) { |
| 155 base::AutoLock auto_lock(sink_lock_); | 159 base::AutoLock auto_lock(sink_lock_); |
| 156 volume_ = volume; | 160 volume_ = volume; |
| 157 if (!client_) | 161 if (!client_) |
| 158 sink_->SetVolume(volume); | 162 sink_->SetVolume(volume); |
| 159 return true; | 163 return true; |
| 160 } | 164 } |
| 161 | 165 |
| 162 void WebAudioSourceProviderImpl::Initialize( | 166 void WebAudioSourceProviderImpl::Initialize( |
| 163 const media::AudioParameters& params, | 167 const AudioParameters& params, |
| 164 RenderCallback* renderer) { | 168 RenderCallback* renderer) { |
| 165 base::AutoLock auto_lock(sink_lock_); | 169 base::AutoLock auto_lock(sink_lock_); |
| 166 CHECK(!renderer_); | 170 CHECK(!renderer_); |
| 167 renderer_ = renderer; | 171 renderer_ = renderer; |
| 168 | 172 |
| 169 DCHECK_EQ(state_, kStopped); | 173 DCHECK_EQ(state_, kStopped); |
| 170 sink_->Initialize(params, renderer); | 174 sink_->Initialize(params, renderer); |
| 171 | 175 |
| 172 // Keep track of the format in case the client hasn't yet been set. | 176 // Keep track of the format in case the client hasn't yet been set. |
| 173 channels_ = params.channels(); | 177 channels_ = params.channels(); |
| 174 sample_rate_ = params.sample_rate(); | 178 sample_rate_ = params.sample_rate(); |
| 175 | 179 |
| 176 if (!set_format_cb_.is_null()) | 180 if (!set_format_cb_.is_null()) |
| 177 base::ResetAndReturn(&set_format_cb_).Run(); | 181 base::ResetAndReturn(&set_format_cb_).Run(); |
| 178 } | 182 } |
| 179 | 183 |
| 180 void WebAudioSourceProviderImpl::OnSetFormat() { | 184 void WebAudioSourceProviderImpl::OnSetFormat() { |
| 181 base::AutoLock auto_lock(sink_lock_); | 185 base::AutoLock auto_lock(sink_lock_); |
| 182 if (!client_) | 186 if (!client_) |
| 183 return; | 187 return; |
| 184 | 188 |
| 185 // Inform Blink about the audio stream format. | 189 // Inform Blink about the audio stream format. |
| 186 client_->setFormat(channels_, sample_rate_); | 190 client_->setFormat(channels_, sample_rate_); |
| 187 } | 191 } |
| 188 | 192 |
| 189 } // namespace content | 193 } // namespace media |
| OLD | NEW |