diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-10 00:43:48 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-10 00:43:48 +0000 |
commit | 4a914885277b01356a75c5b89ccbde3322500c49 (patch) | |
tree | 063fa3850b161c7a15ce1697e3ddfc7d3287b2a2 /webkit/media | |
parent | ec40ca58fb8d99e47d68ee9bacc98f97548d98c2 (diff) | |
download | chromium_src-4a914885277b01356a75c5b89ccbde3322500c49.zip chromium_src-4a914885277b01356a75c5b89ccbde3322500c49.tar.gz chromium_src-4a914885277b01356a75c5b89ccbde3322500c49.tar.bz2 |
Refactor content::RenderAudioSourceProvider as webkit_media::WebAudioSourceProviderImpl.
Doing so prevents the silliness of passing the same pointer into WebMediaPlayerParams twice. Furthermore, the switch-checking logic and render view ID code is better contained as part of RenderViewImpl as opposed to being stuffed inside RenderAudioSourceProvider's constructor.
BUG=136442
Review URL: https://codereview.chromium.org/11830004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@175948 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/media')
-rw-r--r-- | webkit/media/webaudiosourceprovider_impl.cc | 136 | ||||
-rw-r--r-- | webkit/media/webaudiosourceprovider_impl.h | 79 | ||||
-rw-r--r-- | webkit/media/webkit_media.gypi | 2 | ||||
-rw-r--r-- | webkit/media/webmediaplayer_impl.cc | 13 | ||||
-rw-r--r-- | webkit/media/webmediaplayer_impl.h | 10 | ||||
-rw-r--r-- | webkit/media/webmediaplayer_params.cc | 4 | ||||
-rw-r--r-- | webkit/media/webmediaplayer_params.h | 17 |
7 files changed, 226 insertions, 35 deletions
diff --git a/webkit/media/webaudiosourceprovider_impl.cc b/webkit/media/webaudiosourceprovider_impl.cc new file mode 100644 index 0000000..3d2bfb1 --- /dev/null +++ b/webkit/media/webaudiosourceprovider_impl.cc @@ -0,0 +1,136 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/media/webaudiosourceprovider_impl.h" + +#include <vector> + +#include "base/logging.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebAudioSourceProviderClient.h" + +using WebKit::WebVector; + +namespace webkit_media { + +WebAudioSourceProviderImpl::WebAudioSourceProviderImpl( + const scoped_refptr<media::AudioRendererSink>& sink) + : is_initialized_(false), + channels_(0), + sample_rate_(0), + is_running_(false), + renderer_(NULL), + client_(NULL), + sink_(sink) { +} + +WebAudioSourceProviderImpl::~WebAudioSourceProviderImpl() {} + +void WebAudioSourceProviderImpl::setClient( + WebKit::WebAudioSourceProviderClient* client) { + base::AutoLock auto_lock(sink_lock_); + + if (client && client != client_) { + // Detach the audio renderer from normal playback. + sink_->Stop(); + + // The client will now take control by calling provideInput() periodically. + client_ = client; + + if (is_initialized_) { + // The client needs to be notified of the audio format, if available. + // If the format is not yet available, we'll be notified later + // when Initialize() is called. + + // Inform WebKit about the audio stream format. + client->setFormat(channels_, sample_rate_); + } + } else if (!client && client_) { + // Restore normal playback. + client_ = NULL; + // TODO(crogers): We should call sink_->Play() if we're + // in the playing state. + } +} + +void WebAudioSourceProviderImpl::provideInput( + const WebVector<float*>& audio_data, size_t number_of_frames) { + DCHECK(client_); + + if (renderer_ && is_initialized_ && is_running_) { + // Wrap WebVector as std::vector. + std::vector<float*> v(audio_data.size()); + for (size_t i = 0; i < audio_data.size(); ++i) + v[i] = audio_data[i]; + + scoped_ptr<media::AudioBus> audio_bus = media::AudioBus::WrapVector( + number_of_frames, v); + + // TODO(crogers): figure out if we should volume scale here or in common + // WebAudio code. In any case we need to take care of volume. + renderer_->Render(audio_bus.get(), 0); + return; + } + + // Provide silence if the source is not running. + for (size_t i = 0; i < audio_data.size(); ++i) + memset(audio_data[i], 0, sizeof(*audio_data[0]) * number_of_frames); +} + +void WebAudioSourceProviderImpl::Start() { + base::AutoLock auto_lock(sink_lock_); + if (!client_) + sink_->Start(); + is_running_ = true; +} + +void WebAudioSourceProviderImpl::Stop() { + base::AutoLock auto_lock(sink_lock_); + if (!client_) + sink_->Stop(); + is_running_ = false; +} + +void WebAudioSourceProviderImpl::Play() { + base::AutoLock auto_lock(sink_lock_); + if (!client_) + sink_->Play(); + is_running_ = true; +} + +void WebAudioSourceProviderImpl::Pause(bool flush) { + base::AutoLock auto_lock(sink_lock_); + if (!client_) + sink_->Pause(flush); + is_running_ = false; +} + +bool WebAudioSourceProviderImpl::SetVolume(double volume) { + base::AutoLock auto_lock(sink_lock_); + if (!client_) + sink_->SetVolume(volume); + return true; +} + +void WebAudioSourceProviderImpl::Initialize( + const media::AudioParameters& params, + RenderCallback* renderer) { + base::AutoLock auto_lock(sink_lock_); + CHECK(!is_initialized_); + renderer_ = renderer; + + sink_->Initialize(params, renderer); + + // Keep track of the format in case the client hasn't yet been set. + channels_ = params.channels(); + sample_rate_ = params.sample_rate(); + + if (client_) { + // Inform WebKit about the audio stream format. + client_->setFormat(channels_, sample_rate_); + } + + is_initialized_ = true; +} + +} // namespace webkit_media diff --git a/webkit/media/webaudiosourceprovider_impl.h b/webkit/media/webaudiosourceprovider_impl.h new file mode 100644 index 0000000..888d67f --- /dev/null +++ b/webkit/media/webaudiosourceprovider_impl.h @@ -0,0 +1,79 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBKIT_MEDIA_WEBAUDIOSOURCEPROVIDER_IMPL_H_ +#define WEBKIT_MEDIA_WEBAUDIOSOURCEPROVIDER_IMPL_H_ + +#include "base/synchronization/lock.h" +#include "media/base/audio_renderer_sink.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebAudioSourceProvider.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h" + +namespace WebKit { +class WebAudioSourceProviderClient; +} + +namespace webkit_media { + +// WebAudioSourceProviderImpl provides a bridge between classes: +// WebKit::WebAudioSourceProvider <---> media::AudioRendererSink +// +// WebAudioSourceProviderImpl wraps an existing audio sink that is used unless +// WebKit has set a client via setClient(). While a client is set WebKit will +// periodically call provideInput() to render a certain number of audio +// sample-frames using the sink's RenderCallback to get the data. +// +// THREAD SAFETY: +// It is assumed that the callers to setClient() and provideInput() +// implement appropriate locking for thread safety when making +// these calls. This happens in WebKit. +class WebAudioSourceProviderImpl + : public WebKit::WebAudioSourceProvider, + public media::AudioRendererSink { + public: + explicit WebAudioSourceProviderImpl( + const scoped_refptr<media::AudioRendererSink>& sink); + + // WebKit::WebAudioSourceProvider implementation. + virtual void setClient(WebKit::WebAudioSourceProviderClient* client); + virtual void provideInput(const WebKit::WebVector<float*>& audio_data, + size_t number_of_frames); + + // media::AudioRendererSink implementation. + virtual void Start() OVERRIDE; + virtual void Stop() OVERRIDE; + virtual void Play() OVERRIDE; + virtual void Pause(bool flush) OVERRIDE; + virtual bool SetVolume(double volume) OVERRIDE; + virtual void Initialize(const media::AudioParameters& params, + RenderCallback* renderer) OVERRIDE; + + protected: + virtual ~WebAudioSourceProviderImpl(); + + private: + // Set to true when Initialize() is called. + bool is_initialized_; + int channels_; + int sample_rate_; + + // Tracks if |sink_| has been instructed to consume audio. + bool is_running_; + + // Where audio comes from. + media::AudioRendererSink::RenderCallback* renderer_; + + // When set via setClient() it overrides |sink_| for consuming audio. + WebKit::WebAudioSourceProviderClient* client_; + + // Where audio ends up unless overridden by |client_|. + base::Lock sink_lock_; + scoped_refptr<media::AudioRendererSink> sink_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(WebAudioSourceProviderImpl); +}; + +} // namespace webkit_media + +#endif // WEBKIT_MEDIA_WEBAUDIOSOURCEPROVIDER_IMPL_H_ diff --git a/webkit/media/webkit_media.gypi b/webkit/media/webkit_media.gypi index 52cf375..ade49ea 100644 --- a/webkit/media/webkit_media.gypi +++ b/webkit/media/webkit_media.gypi @@ -81,6 +81,8 @@ 'simple_video_frame_provider.h', 'video_frame_provider.cc', 'video_frame_provider.h', + 'webaudiosourceprovider_impl.cc', + 'webaudiosourceprovider_impl.h', 'webmediaplayer_delegate.h', 'webmediaplayer_impl.cc', 'webmediaplayer_impl.h', diff --git a/webkit/media/webmediaplayer_impl.cc b/webkit/media/webmediaplayer_impl.cc index 4b27e48..fee9545 100644 --- a/webkit/media/webmediaplayer_impl.cc +++ b/webkit/media/webmediaplayer_impl.cc @@ -33,6 +33,7 @@ #include "v8/include/v8.h" #include "webkit/media/buffered_data_source.h" #include "webkit/media/filter_helpers.h" +#include "webkit/media/webaudiosourceprovider_impl.h" #include "webkit/media/webmediaplayer_delegate.h" #include "webkit/media/webmediaplayer_params.h" #include "webkit/media/webmediaplayer_proxy.h" @@ -139,8 +140,6 @@ WebMediaPlayerImpl::WebMediaPlayerImpl( media_log_(params.media_log()), accelerated_compositing_reported_(false), incremented_externally_allocated_memory_(false), - audio_source_provider_(params.audio_source_provider()), - audio_renderer_sink_(params.audio_renderer_sink()), is_local_source_(false), supports_save_(true), starting_(false) { @@ -198,13 +197,11 @@ WebMediaPlayerImpl::WebMediaPlayerImpl( proxy_->set_frame_provider(video_renderer); // Create default audio renderer using the null sink if no sink was provided. - scoped_refptr<media::AudioRendererSink> audio_renderer_sink = - params.audio_renderer_sink(); - if (!audio_renderer_sink) - audio_renderer_sink = new media::NullAudioSink(); - + audio_source_provider_ = new WebAudioSourceProviderImpl( + params.audio_renderer_sink() ? params.audio_renderer_sink() : + new media::NullAudioSink()); filter_collection_->AddAudioRenderer(new media::AudioRendererImpl( - audio_renderer_sink, set_decryptor_ready_cb)); + audio_source_provider_, set_decryptor_ready_cb)); } WebMediaPlayerImpl::~WebMediaPlayerImpl() { diff --git a/webkit/media/webmediaplayer_impl.h b/webkit/media/webmediaplayer_impl.h index e9f8cd5..053fcf1 100644 --- a/webkit/media/webmediaplayer_impl.h +++ b/webkit/media/webmediaplayer_impl.h @@ -80,6 +80,7 @@ class MediaLog; namespace webkit_media { class MediaStreamClient; +class WebAudioSourceProviderImpl; class WebMediaPlayerDelegate; class WebMediaPlayerParams; class WebMediaPlayerProxy; @@ -325,13 +326,8 @@ class WebMediaPlayerImpl bool incremented_externally_allocated_memory_; - // TODO(scherkus): Sadly these two objects are the same and we're also forced - // to maintain an additional reference to |audio_renderer_sink_| otherwise - // |audio_source_provider_| will go bad after |pipeline_| shuts down. - // - // See http://crbug.com/136442 for details. - WebKit::WebAudioSourceProvider* audio_source_provider_; - scoped_refptr<media::AudioRendererSink> audio_renderer_sink_; + // Routes audio playback to either AudioRendererSink or WebAudio. + scoped_refptr<WebAudioSourceProviderImpl> audio_source_provider_; bool is_local_source_; bool supports_save_; diff --git a/webkit/media/webmediaplayer_params.cc b/webkit/media/webmediaplayer_params.cc index b860531..1f24625 100644 --- a/webkit/media/webmediaplayer_params.cc +++ b/webkit/media/webmediaplayer_params.cc @@ -10,13 +10,11 @@ namespace webkit_media { WebMediaPlayerParams::WebMediaPlayerParams( - WebKit::WebAudioSourceProvider* audio_source_provider, const scoped_refptr<media::AudioRendererSink>& audio_renderer_sink, const scoped_refptr<media::GpuVideoDecoder::Factories>& gpu_factories, MediaStreamClient* media_stream_client, const scoped_refptr<media::MediaLog>& media_log) - : audio_source_provider_(audio_source_provider), - audio_renderer_sink_(audio_renderer_sink), + : audio_renderer_sink_(audio_renderer_sink), gpu_factories_(gpu_factories), media_stream_client_(media_stream_client), media_log_(media_log) { diff --git a/webkit/media/webmediaplayer_params.h b/webkit/media/webmediaplayer_params.h index d78f78f..577d04c 100644 --- a/webkit/media/webmediaplayer_params.h +++ b/webkit/media/webmediaplayer_params.h @@ -13,10 +13,6 @@ class AudioRendererSink; class MediaLog; } -namespace WebKit { -class WebAudioSourceProvider; -} - namespace webkit_media { class MediaStreamClient; @@ -26,25 +22,13 @@ class MediaStreamClient; class WebMediaPlayerParams { public: // |media_log| is the only required parameter; all others may be null. - // - // If provided, |audio_source_provider| and |audio_renderer_sink| arguments - // must be the same object. - // - // TODO(scherkus): Remove WebAudioSourceProvider parameter once we - // refactor RenderAudioSourceProvider to live under webkit/media/ - // instead of content/renderer/, see http://crbug.com/136442 WebMediaPlayerParams( - WebKit::WebAudioSourceProvider* audio_source_provider, const scoped_refptr<media::AudioRendererSink>& audio_renderer_sink, const scoped_refptr<media::GpuVideoDecoder::Factories>& gpu_factories, MediaStreamClient* media_stream_client, const scoped_refptr<media::MediaLog>& media_log); ~WebMediaPlayerParams(); - WebKit::WebAudioSourceProvider* audio_source_provider() const { - return audio_source_provider_; - } - const scoped_refptr<media::AudioRendererSink>& audio_renderer_sink() const { return audio_renderer_sink_; } @@ -63,7 +47,6 @@ class WebMediaPlayerParams { } private: - WebKit::WebAudioSourceProvider* audio_source_provider_; scoped_refptr<media::AudioRendererSink> audio_renderer_sink_; scoped_refptr<media::GpuVideoDecoder::Factories> gpu_factories_; MediaStreamClient* media_stream_client_; |