summaryrefslogtreecommitdiffstats
path: root/chrome/renderer
diff options
context:
space:
mode:
authorneb@chromium.org <neb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-08 21:08:19 +0000
committerneb@chromium.org <neb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-08 21:08:19 +0000
commit7d74aaab9390a7502dac835ddcd2a5175224702e (patch)
tree4baccf95f53be95803724bce220436bacf5ccce0 /chrome/renderer
parent22c379ac0a813d0b3e0fd34819aad2d3e48c39b7 (diff)
downloadchromium_src-7d74aaab9390a7502dac835ddcd2a5175224702e.zip
chromium_src-7d74aaab9390a7502dac835ddcd2a5175224702e.tar.gz
chromium_src-7d74aaab9390a7502dac835ddcd2a5175224702e.tar.bz2
Implement low-latency audio on Pepper.
BUG=28292 TEST=none Review URL: http://codereview.chromium.org/577019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38392 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r--chrome/renderer/audio_message_filter.cc23
-rw-r--r--chrome/renderer/audio_message_filter.h18
-rw-r--r--chrome/renderer/audio_message_filter_unittest.cc5
-rw-r--r--chrome/renderer/media/audio_renderer_impl.cc6
-rw-r--r--chrome/renderer/media/audio_renderer_impl.h3
-rw-r--r--chrome/renderer/pepper_devices.cc72
-rw-r--r--chrome/renderer/pepper_devices.h23
7 files changed, 138 insertions, 12 deletions
diff --git a/chrome/renderer/audio_message_filter.cc b/chrome/renderer/audio_message_filter.cc
index 31c1df4..de209d9 100644
--- a/chrome/renderer/audio_message_filter.cc
+++ b/chrome/renderer/audio_message_filter.cc
@@ -35,6 +35,8 @@ bool AudioMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(AudioMessageFilter, message)
IPC_MESSAGE_HANDLER(ViewMsg_RequestAudioPacket, OnRequestPacket)
IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamCreated, OnStreamCreated)
+ IPC_MESSAGE_HANDLER(ViewMsg_NotifyLowLatencyAudioStreamCreated,
+ OnLowLatencyStreamCreated)
IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamStateChanged,
OnStreamStateChanged)
IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamVolume, OnStreamVolume)
@@ -84,6 +86,27 @@ void AudioMessageFilter::OnStreamCreated(int stream_id,
delegate->OnCreated(handle, length);
}
+void AudioMessageFilter::OnLowLatencyStreamCreated(
+ int stream_id,
+ base::SharedMemoryHandle handle,
+#if defined(OS_WIN)
+ base::SyncSocket::Handle socket_handle,
+#else
+ base::FileDescriptor socket_descriptor,
+#endif
+ uint32 length) {
+ Delegate* delegate = delegates_.Lookup(stream_id);
+ if (!delegate) {
+ DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
+ " audio renderer.";
+ return;
+ }
+#if !defined(OS_WIN)
+ base::SyncSocket::Handle socket_handle = socket_descriptor.fd;
+#endif
+ delegate->OnLowLatencyCreated(handle, socket_handle, length);
+}
+
void AudioMessageFilter::OnStreamStateChanged(
int stream_id,
const ViewMsg_AudioStreamState_Params& state) {
diff --git a/chrome/renderer/audio_message_filter.h b/chrome/renderer/audio_message_filter.h
index 3dfacdc..6b4f736 100644
--- a/chrome/renderer/audio_message_filter.h
+++ b/chrome/renderer/audio_message_filter.h
@@ -12,6 +12,7 @@
#include "base/id_map.h"
#include "base/shared_memory.h"
+#include "base/sync_socket.h"
#include "base/time.h"
#include "ipc/ipc_channel_proxy.h"
#include "testing/gtest/include/gtest/gtest_prod.h"
@@ -33,6 +34,12 @@ class AudioMessageFilter : public IPC::ChannelProxy::MessageFilter {
// Called when an audio stream has been created in the browser process.
virtual void OnCreated(base::SharedMemoryHandle handle, uint32 length) = 0;
+ // Called when a low-latency audio stream has been created in the browser
+ // process.
+ virtual void OnLowLatencyCreated(base::SharedMemoryHandle handle,
+ base::SyncSocket::Handle socket_handle,
+ uint32 length) = 0;
+
// Called when notification of stream volume is received from the browser
// process.
virtual void OnVolume(double volume) = 0;
@@ -76,6 +83,17 @@ class AudioMessageFilter : public IPC::ChannelProxy::MessageFilter {
void OnStreamCreated(int stream_id, base::SharedMemoryHandle handle,
uint32 length);
+ // Received when browser process has created an audio output stream of low
+ // latency.
+ void OnLowLatencyStreamCreated(int stream_id, base::SharedMemoryHandle handle,
+#if defined(OS_WIN)
+ base::SyncSocket::Handle socket_handle,
+#else
+ base::FileDescriptor socket_descriptor,
+#endif
+ uint32 length);
+
+
// Received when internal state of browser process' audio output device has
// changed.
void OnStreamStateChanged(int stream_id,
diff --git a/chrome/renderer/audio_message_filter_unittest.cc b/chrome/renderer/audio_message_filter_unittest.cc
index 3dce864..e4be68c 100644
--- a/chrome/renderer/audio_message_filter_unittest.cc
+++ b/chrome/renderer/audio_message_filter_unittest.cc
@@ -34,6 +34,11 @@ class MockAudioDelegate : public AudioMessageFilter::Delegate {
length_ = length;
}
+ virtual void OnLowLatencyCreated(base::SharedMemoryHandle handle,
+ base::SyncSocket::Handle,
+ uint32 length) {
+ }
+
virtual void OnVolume(double volume) {
volume_received_ = true;
volume_ = volume;
diff --git a/chrome/renderer/media/audio_renderer_impl.cc b/chrome/renderer/media/audio_renderer_impl.cc
index 3aba1c1..b03ba9e 100644
--- a/chrome/renderer/media/audio_renderer_impl.cc
+++ b/chrome/renderer/media/audio_renderer_impl.cc
@@ -174,6 +174,12 @@ void AudioRendererImpl::OnCreated(base::SharedMemoryHandle handle,
shared_memory_size_ = length;
}
+void AudioRendererImpl::OnLowLatencyCreated(base::SharedMemoryHandle,
+ base::SyncSocket::Handle, uint32) {
+ // AudioRenderer should not have a low-latency audio channel.
+ NOTREACHED();
+}
+
void AudioRendererImpl::OnRequestPacket(uint32 bytes_in_buffer,
const base::Time& message_timestamp) {
DCHECK(MessageLoop::current() == io_loop_);
diff --git a/chrome/renderer/media/audio_renderer_impl.h b/chrome/renderer/media/audio_renderer_impl.h
index 2c4d990..2e714ee 100644
--- a/chrome/renderer/media/audio_renderer_impl.h
+++ b/chrome/renderer/media/audio_renderer_impl.h
@@ -122,6 +122,9 @@ class AudioRendererImpl : public media::AudioRendererBase,
const base::Time& message_timestamp);
void OnStateChanged(const ViewMsg_AudioStreamState_Params& state);
void OnCreated(base::SharedMemoryHandle handle, uint32 length);
+ void OnLowLatencyCreated(base::SharedMemoryHandle handle,
+ base::SyncSocket::Handle socket_handle,
+ uint32 length);
void OnVolume(double volume);
// Methods called on pipeline thread ----------------------------------------
diff --git a/chrome/renderer/pepper_devices.cc b/chrome/renderer/pepper_devices.cc
index 3b14d16..4a831f4 100644
--- a/chrome/renderer/pepper_devices.cc
+++ b/chrome/renderer/pepper_devices.cc
@@ -98,14 +98,18 @@ AudioDeviceContext::~AudioDeviceContext() {
}
}
-NPError AudioDeviceContext::Initialize(
- AudioMessageFilter* filter, const NPDeviceContextAudioConfig* config,
- NPDeviceContextAudio* context) {
- filter_ = filter;
- context_= context;
+NPError AudioDeviceContext::Initialize(AudioMessageFilter* filter,
+ const NPDeviceContextAudioConfig* config,
+ NPDeviceContextAudio* context) {
+ DCHECK(filter);
// Make sure we don't call init more than once.
DCHECK_EQ(0, stream_id_);
- stream_id_ = filter_->AddDelegate(this);
+
+ if (!config || !context) {
+ return NPERR_INVALID_PARAM;
+ }
+ filter_ = filter;
+ context_= context;
ViewHostMsg_Audio_CreateStream_Params params;
params.format = AudioManager::AUDIO_PCM_LINEAR;
@@ -133,6 +137,7 @@ NPError AudioDeviceContext::Initialize(
config->sampleFrameCount << "Hz, " << params.bits_per_sample <<
" bits, " << config->outputChannelMap << "channels";
+ stream_id_ = filter_->AddDelegate(this);
filter->Send(new ViewHostMsg_CreateAudioStream(0, stream_id_, params));
return NPERR_NO_ERROR;
}
@@ -143,13 +148,17 @@ void AudioDeviceContext::OnDestroy() {
filter_->RemoveDelegate(stream_id_);
filter_->Send(new ViewHostMsg_CloseAudioStream(0, stream_id_));
stream_id_ = 0;
+ if (audio_thread_.get()) {
+ socket_->Close();
+ audio_thread_->Join();
+ }
}
void AudioDeviceContext::OnRequestPacket(
uint32 bytes_in_buffer, const base::Time& message_timestamp) {
- context_->config.callback(context_);
+ FireAudioCallback();
filter_->Send(new ViewHostMsg_NotifyAudioPacketReady(0, stream_id_,
- shared_memory_size_));
+ shared_memory_size_));
}
void AudioDeviceContext::OnStateChanged(
@@ -158,15 +167,60 @@ void AudioDeviceContext::OnStateChanged(
void AudioDeviceContext::OnCreated(
base::SharedMemoryHandle handle, uint32 length) {
+#if defined(OS_WIN)
+ DCHECK(handle);
+#else
+ DCHECK_NE(-1, handle.fd);
+#endif
+ DCHECK(length);
+ DCHECK(context_);
+
+ shared_memory_.reset(new base::SharedMemory(handle, false));
+ shared_memory_->Map(length);
+ shared_memory_size_ = length;
+
+ context_->outBuffer = shared_memory_->memory();
+ FireAudioCallback();
+ filter_->Send(new ViewHostMsg_PlayAudioStream(0, stream_id_));
+}
+
+void AudioDeviceContext::OnLowLatencyCreated(
+ base::SharedMemoryHandle handle, base::SyncSocket::Handle socket_handle,
+ uint32 length) {
+#if defined(OS_WIN)
+ DCHECK(handle);
+ DCHECK(socket_handle);
+#else
+ DCHECK_NE(-1, handle.fd);
+ DCHECK_NE(-1, socket_handle);
+#endif
+ DCHECK(length);
+ DCHECK(context_);
+ DCHECK(!audio_thread_.get());
shared_memory_.reset(new base::SharedMemory(handle, false));
shared_memory_->Map(length);
shared_memory_size_ = length;
context_->outBuffer = shared_memory_->memory();
- // TODO(neb): call play after prefilling
+ socket_.reset(new base::SyncSocket(socket_handle));
+ if (context_->config.callback) {
+ FireAudioCallback();
+ audio_thread_.reset(
+ new base::DelegateSimpleThread(this, "plugin_audio_thread"));
+ audio_thread_->Start();
+ }
filter_->Send(new ViewHostMsg_PlayAudioStream(0, stream_id_));
}
void AudioDeviceContext::OnVolume(double volume) {
}
+void AudioDeviceContext::Run() {
+ int pending_data;
+ while (sizeof(pending_data) == socket_->Receive(&pending_data,
+ sizeof(pending_data)) &&
+ pending_data >= 0) {
+ FireAudioCallback();
+ }
+}
+
diff --git a/chrome/renderer/pepper_devices.h b/chrome/renderer/pepper_devices.h
index 31a2d11..2aa0b54 100644
--- a/chrome/renderer/pepper_devices.h
+++ b/chrome/renderer/pepper_devices.h
@@ -9,6 +9,7 @@
#include "base/scoped_ptr.h"
#include "base/shared_memory.h"
+#include "base/simple_thread.h"
#include "base/gfx/rect.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/transport_dib.h"
@@ -46,7 +47,8 @@ class Graphics2DDeviceContext {
// Each instance of AudioDeviceContext corresponds to one host stream (and one
// audio context). NPDeviceContextAudio contains the id of the context's
// stream in the privatePtr member.
-class AudioDeviceContext : public AudioMessageFilter::Delegate {
+class AudioDeviceContext : public AudioMessageFilter::Delegate,
+ public base::DelegateSimpleThread::Delegate {
public:
// TODO(neb): if plugin_delegate parameter is indeed unused, remove it
explicit AudioDeviceContext() : stream_id_(0) {
@@ -57,24 +59,39 @@ class AudioDeviceContext : public AudioMessageFilter::Delegate {
const NPDeviceContextAudioConfig* config,
NPDeviceContextAudio* context);
+ base::SharedMemory* shared_memory() { return shared_memory_.get(); }
+
+ private:
+
// AudioMessageFilter::Delegate implementation
virtual void OnRequestPacket(uint32 bytes_in_buffer,
const base::Time& message_timestamp);
virtual void OnStateChanged(const ViewMsg_AudioStreamState_Params& state);
virtual void OnCreated(base::SharedMemoryHandle handle, uint32 length);
+ virtual void OnLowLatencyCreated(base::SharedMemoryHandle handle,
+ base::SyncSocket::Handle socket_handle,
+ uint32 length);
virtual void OnVolume(double volume);
// End of AudioMessageFilter::Delegate implementation
- base::SharedMemory* shared_memory() { return shared_memory_.get(); }
+ // DelegateSimpleThread::Delegate implementation
+ virtual void Run();
+ // End of DelegateSimpleThread::Delegate implementation
- private:
void OnDestroy();
+ void FireAudioCallback() {
+ if (context_ && context_->config.callback) {
+ context_->config.callback(context_);
+ }
+ }
NPDeviceContextAudio* context_;
scoped_refptr<AudioMessageFilter> filter_;
int32 stream_id_;
scoped_ptr<base::SharedMemory> shared_memory_;
uint32 shared_memory_size_;
+ scoped_ptr<base::SyncSocket> socket_;
+ scoped_ptr<base::DelegateSimpleThread> audio_thread_;
};
#endif // CHROME_RENDERER_PEPPER_DEVICES_H_