summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/media
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-10 22:40:31 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-10 22:40:31 +0000
commit8db216ee756d4e06fbd05676b045784da3a5928c (patch)
tree36b7bf2b42bf6ccb1fab70cfbe35dd29514c9cb7 /chrome/renderer/media
parente00e0cc2284c3a8e0b74841ace6b9dad9bd1df94 (diff)
downloadchromium_src-8db216ee756d4e06fbd05676b045784da3a5928c.zip
chromium_src-8db216ee756d4e06fbd05676b045784da3a5928c.tar.gz
chromium_src-8db216ee756d4e06fbd05676b045784da3a5928c.tar.bz2
Implemented AudioRendererImpl in renderer process using API
provided by RenderView for accessing audio device in the browser using IPC, subclassing from media::AudioRendererBase for buffer filling. Review URL: http://codereview.chromium.org/28081 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@11392 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/media')
-rw-r--r--chrome/renderer/media/audio_renderer_impl.cc150
-rw-r--r--chrome/renderer/media/audio_renderer_impl.h163
2 files changed, 279 insertions, 34 deletions
diff --git a/chrome/renderer/media/audio_renderer_impl.cc b/chrome/renderer/media/audio_renderer_impl.cc
index 9dbd392..5df76ba 100644
--- a/chrome/renderer/media/audio_renderer_impl.cc
+++ b/chrome/renderer/media/audio_renderer_impl.cc
@@ -3,50 +3,160 @@
// LICENSE file.
#include "chrome/renderer/media/audio_renderer_impl.h"
+#include "chrome/renderer/render_view.h"
+#include "chrome/renderer/render_thread.h"
+#include "chrome/renderer/webmediaplayer_delegate_impl.h"
+#include "media/base/filter_host.h"
+
+// We'll try to fill 4096 samples per buffer, which is roughly ~92ms of audio
+// data for a 44.1kHz audio source.
+static const size_t kSamplesPerBuffer = 4096;
AudioRendererImpl::AudioRendererImpl(WebMediaPlayerDelegateImpl* delegate)
- : delegate_(delegate) {
+ : AudioRendererBase(kDefaultMaxQueueSize),
+ delegate_(delegate),
+ stream_id_(0),
+ shared_memory_(NULL),
+ shared_memory_size_(0),
+ packet_requested_(false),
+ render_loop_(RenderThread::current()->message_loop()),
+ resource_release_event_(true, false) {
+ // TODO(hclam): do we need to move this method call to render thread?
+ delegate_->SetAudioRenderer(this);
}
AudioRendererImpl::~AudioRendererImpl() {
}
-void AudioRendererImpl::Stop() {
- // TODO(scherkus): implement Stop.
- NOTIMPLEMENTED();
+bool AudioRendererImpl::IsMediaFormatSupported(
+ const media::MediaFormat* media_format) {
+ int channels;
+ int sample_rate;
+ int sample_bits;
+ return ParseMediaFormat(media_format, &channels, &sample_rate, &sample_bits);
}
-bool AudioRendererImpl::Initialize(media::AudioDecoder* decoder) {
- // TODO(scherkus): implement Initialize.
- NOTIMPLEMENTED();
- return false;
+bool AudioRendererImpl::OnInitialize(const media::MediaFormat* media_format) {
+ // Parse integer values in MediaFormat.
+ int channels;
+ int sample_rate;
+ int sample_bits;
+ if (!ParseMediaFormat(media_format, &channels, &sample_rate, &sample_bits)) {
+ return false;
+ }
+
+ // Create the audio output stream in browser process.
+ size_t packet_size = kSamplesPerBuffer * channels * sample_bits / 8;
+ render_loop_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &AudioRendererImpl::OnCreateAudioStream,
+ AudioManager::AUDIO_PCM_LINEAR, channels, sample_rate, sample_bits,
+ packet_size));
+ return true;
}
-void AudioRendererImpl::SetVolume(float volume) {
- // TODO(scherkus): implement SetVolume.
- NOTIMPLEMENTED();
+void AudioRendererImpl::OnStop() {
+ if (!resource_release_event_.IsSignaled()) {
+ render_loop_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &AudioRendererImpl::ReleaseRendererResources));
+ resource_release_event_.Wait();
+ }
}
-bool AudioRendererImpl::IsMediaFormatSupported(
- const media::MediaFormat* format) {
- // TODO(hclam): check the format correct.
- return true;
+void AudioRendererImpl::OnAssignment(media::Buffer* buffer_in) {
+ // Use the base class to queue the buffer.
+ AudioRendererBase::OnAssignment(buffer_in);
+ // Post a task to render thread to notify a packet reception.
+ render_loop_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &AudioRendererImpl::OnNotifyAudioPacketReady));
}
-void AudioRendererImpl::OnRequestPacket() {
- // TODO(hclam): implement this.
+void AudioRendererImpl::SetPlaybackRate(float rate) {
+ // TODO(hclam): handle playback rates not equal to 1.0.
+ if (rate == 1.0f) {
+ // TODO(hclam): what should I do here? OnCreated has fired StartAudioStream
+ // in the browser process, it seems there's nothing to do here.
+ } else {
+ NOTIMPLEMENTED();
+ }
+}
+
+void AudioRendererImpl::SetVolume(float volume) {
+ // TODO(hclam): change this to multichannel if possible.
+ render_loop_->PostTask(FROM_HERE,
+ NewRunnableMethod(
+ this, &AudioRendererImpl::OnSetAudioVolume, volume, volume));
}
void AudioRendererImpl::OnCreated(base::SharedMemoryHandle handle,
size_t length) {
- // TODO(hclam): implement this.
+ shared_memory_.reset(new base::SharedMemory(handle, false));
+ shared_memory_size_ = length;
+ // TODO(hclam): is there any better place to do this?
+ OnStartAudioStream();
+}
+
+void AudioRendererImpl::OnRequestPacket() {
+ packet_requested_ = true;
}
void AudioRendererImpl::OnStateChanged(AudioOutputStream::State state,
int info) {
- // TODO(hclam): implement this.
+ switch (state) {
+ case AudioOutputStream::STATE_ERROR:
+ host_->Error(media::PIPELINE_ERROR_AUDIO_HARDWARE);
+ break;
+ // TODO(hclam): handle these events.
+ case AudioOutputStream::STATE_STARTED:
+ case AudioOutputStream::STATE_PAUSED:
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
}
void AudioRendererImpl::OnVolume(double left, double right) {
- // TODO(hclam): implement this.
+ // TODO(hclam): decide whether we need to report the current volume to
+ // pipeline.
+}
+
+void AudioRendererImpl::ReleaseRendererResources() {
+ OnCloseAudioStream();
+ resource_release_event_.Signal();
+}
+
+void AudioRendererImpl::OnCreateAudioStream(
+ AudioManager::Format format, int channels, int sample_rate,
+ int bits_per_sample, size_t packet_size) {
+ stream_id_ = delegate_->view()->CreateAudioStream(
+ this, format, channels, sample_rate, bits_per_sample, packet_size);
+}
+
+void AudioRendererImpl::OnStartAudioStream() {
+ delegate_->view()->StartAudioStream(stream_id_);
+}
+
+void AudioRendererImpl::OnCloseAudioStream() {
+ // Unregister ourself from RenderView, we will not be called anymore.
+ delegate_->view()->CloseAudioStream(stream_id_);
+}
+
+void AudioRendererImpl::OnSetAudioVolume(double left, double right) {
+ delegate_->view()->SetAudioVolume(stream_id_, left, right);
+}
+
+void AudioRendererImpl::OnNotifyAudioPacketReady() {
+ if (packet_requested_) {
+ DCHECK(shared_memory_.get());
+ // Fill into the shared memory.
+ size_t filled = FillBuffer(static_cast<uint8*>(shared_memory_->memory()),
+ shared_memory_size_);
+ packet_requested_ = false;
+ // Then tell browser process we are done filling into the buffer.
+ delegate_->view()->NotifyAudioPacketReady(stream_id_, filled);
+ }
+}
+
+const media::MediaFormat* AudioRendererImpl::GetMediaFormat() {
+ return &media_format_;
}
diff --git a/chrome/renderer/media/audio_renderer_impl.h b/chrome/renderer/media/audio_renderer_impl.h
index 9d6b0b4..c0a8257 100644
--- a/chrome/renderer/media/audio_renderer_impl.h
+++ b/chrome/renderer/media/audio_renderer_impl.h
@@ -1,49 +1,184 @@
// Copyright (c) 2009 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.
+//
+// Audio rendering unit utilizing audio output stream provided by browser
+// process through IPC.
+//
+// Relationship of classes.
+//
+// AudioRendererHost AudioRendererImpl
+// ^ ^
+// | |
+// v IPC v
+// ResourceMessageFilter <---------> RenderView
+//
+// Implementation of interface with audio device is in AudioRendererHost and
+// it provides services and entry points in ResourceMessageFilter, allowing
+// usage of IPC calls to interact with audio device. RenderView acts as a portal
+// for IPC calls and does no more than delegation.
+//
+// Transportation of audio buffer is done by using shared memory, after
+// OnCreateAudioStream is executed, OnCreated would be called along with a
+// SharedMemoryHandle upon successful creation of audio output stream in the
+// browser process. The same piece of shared memory would be used during the
+// lifetime of this unit.
+//
+// This class lives inside three threads during it's lifetime, namely:
+// 1. Render thread
+// The thread within which this class is constructed and destroyed,
+// interfacing with RenderView should only happen here.
+// 2. Pipeline thread
+// Initialization of filter and proper stopping of filters happens here.
+// Properties of this filter is also set in this thread.
+// 3. Audio decoder thread (If there's one.)
+// Responsible for decoding audio data and gives raw PCM data to this object.
+//
+// Methods categorized according to the thread(s) they are running on.
+//
+// Render thread
+// +-- CreateFactory()
+// | Helper method for construction this class.
+// |-- IsMetidFormatSupported()
+// | Helper method to identify media formats accepted by this class for
+// | construction.
+// |-- OnCreateAudioStream()
+// | Calls RenderView::CreateAudioStream().
+// |-- OnStartAudioStream()
+// | Calls RenderView::StartAudioStream().
+// |-- OnCloseAudioStream()
+// | Calls RenderView::CloseAudioStream().
+// |-- OnSetAudioVolume()
+// | Calls RenderView::SetAudioVolume().
+// |-- OnNotifyAudioPacketReady
+// | Calls RenderView::NotifyAudioPacketReady().
+// |-- OnRequestPacket()
+// | Called from RenderView when an audio packet requested is received
+// | from browser process.
+// |-- OnStateChanged()
+// | Called from RenderView upon state change of the audio output stream
+// | in the browser process. Error of the output stream is reported here.
+// |-- OnCreated()
+// | Called from RenderView upon successful creation of audio output stream
+// | in the browser process, called along with a SharedMemoryHandle.
+// |-- OnVolume()
+// | Called from RenderView about the volume of the audio output stream.
+// \-- ReleaseRendererResource()
+// Release resources that live inside render thread.
+//
+// Pipeline thread
+// +-- AudioRendererImpl()
+// | Constructor method.
+// |-- ~AudioRendererImpl()
+// | Destructor method.
+// |-- SetPlaybackRate()
+// | Given the playback rate information.
+// |-- GetMediaFormat()
+// | Obtain the current media format of this unit.
+// |-- SetVolume()
+// | Given the volume information.
+// |-- OnInitialize()
+// | Called from AudioRendererBase for initialization event.
+// \-- OnStop()
+// Called from AudioRendererBase for stop event.
+//
+// Audio decoder thread (If there's one.)
+// \-- OnAssignment()
+// A raw PCM audio packet buffer is recevied here, this method is called
+// from pipeline thread if audio decoder thread does not exist.
#ifndef CHROME_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_
#define CHROME_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_
#include "base/shared_memory.h"
+#include "base/waitable_event.h"
#include "media/audio/audio_output.h"
#include "media/base/factory.h"
#include "media/base/filters.h"
+#include "media/filters/audio_renderer_base.h"
class WebMediaPlayerDelegateImpl;
-class AudioRendererImpl : public media::AudioRenderer {
+class AudioRendererImpl : public media::AudioRendererBase {
public:
- AudioRendererImpl(WebMediaPlayerDelegateImpl* delegate);
-
- // media::MediaFilter implementation.
- virtual void Stop();
-
- // media::AudioRenderer implementation.
- virtual bool Initialize(media::AudioDecoder* decoder);
- virtual void SetVolume(float volume);
-
- // Static method for creating factory for this object.
+ // Methods called on render thread ------------------------------------------
+ // Methods called during construction.
static media::FilterFactory* CreateFactory(
WebMediaPlayerDelegateImpl* delegate) {
return new media::FilterFactoryImpl1<AudioRendererImpl,
WebMediaPlayerDelegateImpl*>(delegate);
}
-
- // Answers question from the factory to see if we accept |format|.
static bool IsMediaFormatSupported(const media::MediaFormat* format);
+ // Methods call from RenderView when audio related IPC messages are received
+ // from browser process.
void OnRequestPacket();
void OnStateChanged(AudioOutputStream::State state, int info);
void OnCreated(base::SharedMemoryHandle handle, size_t length);
void OnVolume(double left, double right);
+ // Release resources that lives in renderer thread, i.e. audio output streams.
+ void ReleaseRendererResources();
+
+ // Methods called on pipeline thread ----------------------------------------
+ // media::MediaFilter implementation.
+ virtual void SetPlaybackRate(float rate);
+ const media::MediaFormat* GetMediaFormat();
+
+ // media::AudioRenderer implementation.
+ virtual void SetVolume(float volume);
+
+ // AssignableBuffer<AudioRendererBase, BufferInterface> implementation.
+ virtual void OnAssignment(media::Buffer* buffer_in);
+
protected:
- virtual ~AudioRendererImpl();
+ // Methods called on audio renderer thread ----------------------------------
+ // These methods are called from AudioRendererBase.
+ virtual bool OnInitialize(const media::MediaFormat* media_format);
+ virtual void OnStop();
private:
+ friend class media::FilterFactoryImpl1<AudioRendererImpl,
+ WebMediaPlayerDelegateImpl*>;
+
+ explicit AudioRendererImpl(WebMediaPlayerDelegateImpl* delegate);
+ virtual ~AudioRendererImpl();
+
+ // Methods call on render thread --------------------------------------------
+ // The following methods are tasks posted on the render thread that needs to
+ // be executed on that thread. They interact with WebMediaPlayerDelegateImpl
+ // and the containing RenderView, because method calls to RenderView must be
+ // executed on render thread.
+ void OnCreateAudioStream(AudioManager::Format format, int channels,
+ int sample_rate, int bits_per_sample,
+ size_t packet_size);
+ void OnStartAudioStream();
+ void OnCloseAudioStream();
+ void OnSetAudioVolume(double left, double right);
+ void OnNotifyAudioPacketReady();
+
WebMediaPlayerDelegateImpl* delegate_;
+ // A map of media format information.
+ media::MediaFormat media_format_;
+
+ // ID of the stream created in the browser process.
+ int32 stream_id_;
+
+ // Memory shared by the browser process for audio buffer.
+ scoped_ptr<base::SharedMemory> shared_memory_;
+ size_t shared_memory_size_;
+
+ // Flag that tells whether we have any unfulfilled packet request.
+ bool packet_requested_;
+
+ // Message loop for the render thread, it's the message loop where this class
+ // is constructed.
+ MessageLoop* render_loop_;
+
+ // Event for releasing resources that live in render thread.
+ base::WaitableEvent resource_release_event_;
+
DISALLOW_COPY_AND_ASSIGN(AudioRendererImpl);
};