diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-10 22:40:31 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-10 22:40:31 +0000 |
commit | 8db216ee756d4e06fbd05676b045784da3a5928c (patch) | |
tree | 36b7bf2b42bf6ccb1fab70cfbe35dd29514c9cb7 /chrome/renderer/media/audio_renderer_impl.cc | |
parent | e00e0cc2284c3a8e0b74841ace6b9dad9bd1df94 (diff) | |
download | chromium_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/audio_renderer_impl.cc')
-rw-r--r-- | chrome/renderer/media/audio_renderer_impl.cc | 150 |
1 files changed, 130 insertions, 20 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_; } |