summaryrefslogtreecommitdiffstats
path: root/webkit/media
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-10 00:43:48 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-10 00:43:48 +0000
commit4a914885277b01356a75c5b89ccbde3322500c49 (patch)
tree063fa3850b161c7a15ce1697e3ddfc7d3287b2a2 /webkit/media
parentec40ca58fb8d99e47d68ee9bacc98f97548d98c2 (diff)
downloadchromium_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.cc136
-rw-r--r--webkit/media/webaudiosourceprovider_impl.h79
-rw-r--r--webkit/media/webkit_media.gypi2
-rw-r--r--webkit/media/webmediaplayer_impl.cc13
-rw-r--r--webkit/media/webmediaplayer_impl.h10
-rw-r--r--webkit/media/webmediaplayer_params.cc4
-rw-r--r--webkit/media/webmediaplayer_params.h17
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_;