1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/media/audio_renderer_impl.h"
11 #include "base/bind.h"
12 #include "content/common/child_process.h"
13 #include "content/common/media/audio_messages.h"
14 #include "content/renderer/media/audio_hardware.h"
15 #include "content/renderer/render_thread_impl.h"
16 #include "media/audio/audio_buffers_state.h"
17 #include "media/audio/audio_util.h"
18 #include "media/base/filter_host.h"
20 AudioRendererImpl::AudioRendererImpl(media::AudioRendererSink
* sink
)
21 : AudioRendererBase(),
25 is_initialized_(false) {
28 AudioRendererImpl::~AudioRendererImpl() {
31 base::TimeDelta
AudioRendererImpl::ConvertToDuration(int bytes
) {
32 if (bytes_per_second_
) {
33 return base::TimeDelta::FromMicroseconds(
34 base::Time::kMicrosecondsPerSecond
* bytes
/ bytes_per_second_
);
36 return base::TimeDelta();
39 void AudioRendererImpl::UpdateEarliestEndTime(int bytes_filled
,
40 base::TimeDelta request_delay
,
41 base::Time time_now
) {
42 if (bytes_filled
!= 0) {
43 base::TimeDelta predicted_play_time
= ConvertToDuration(bytes_filled
);
44 float playback_rate
= GetPlaybackRate();
45 if (playback_rate
!= 1.0f
) {
46 predicted_play_time
= base::TimeDelta::FromMicroseconds(
47 static_cast<int64
>(ceil(predicted_play_time
.InMicroseconds() *
51 std::max(earliest_end_time_
,
52 time_now
+ request_delay
+ predicted_play_time
);
56 bool AudioRendererImpl::OnInitialize(int bits_per_channel
,
57 ChannelLayout channel_layout
,
59 // We use the AUDIO_PCM_LINEAR flag because AUDIO_PCM_LOW_LATENCY
60 // does not currently support all the sample-rates that we require.
61 // Please see: http://code.google.com/p/chromium/issues/detail?id=103627
63 audio_parameters_
.Reset(
64 media::AudioParameters::AUDIO_PCM_LINEAR
,
65 channel_layout
, sample_rate
, bits_per_channel
,
66 audio_hardware::GetHighLatencyOutputBufferSize(sample_rate
));
68 bytes_per_second_
= audio_parameters_
.GetBytesPerSecond();
72 if (!is_initialized_
) {
73 sink_
->Initialize(audio_parameters_
, this);
76 is_initialized_
= true;
83 void AudioRendererImpl::OnStop() {
93 void AudioRendererImpl::SetPlaybackRate(float rate
) {
94 DCHECK_LE(0.0f
, rate
);
96 // Handle the case where we stopped due to IO message loop dying.
98 AudioRendererBase::SetPlaybackRate(rate
);
102 // We have two cases here:
103 // Play: GetPlaybackRate() == 0.0 && rate != 0.0
104 // Pause: GetPlaybackRate() != 0.0 && rate == 0.0
105 if (GetPlaybackRate() == 0.0f
&& rate
!= 0.0f
) {
107 } else if (GetPlaybackRate() != 0.0f
&& rate
== 0.0f
) {
108 // Pause is easy, we can always pause.
111 AudioRendererBase::SetPlaybackRate(rate
);
114 void AudioRendererImpl::Pause(const base::Closure
& callback
) {
115 AudioRendererBase::Pause(callback
);
122 void AudioRendererImpl::Seek(base::TimeDelta time
,
123 const media::PipelineStatusCB
& cb
) {
124 AudioRendererBase::Seek(time
, cb
);
131 void AudioRendererImpl::Play(const base::Closure
& callback
) {
132 AudioRendererBase::Play(callback
);
136 if (GetPlaybackRate() != 0.0f
) {
143 void AudioRendererImpl::SetVolume(float volume
) {
147 sink_
->SetVolume(volume
);
150 void AudioRendererImpl::DoPlay() {
151 earliest_end_time_
= base::Time::Now();
156 void AudioRendererImpl::DoPause() {
161 void AudioRendererImpl::DoSeek() {
162 earliest_end_time_
= base::Time::Now();
164 // Pause and flush the stream when we seek to a new location.
169 size_t AudioRendererImpl::Render(const std::vector
<float*>& audio_data
,
170 size_t number_of_frames
,
171 size_t audio_delay_milliseconds
) {
172 if (stopped_
|| GetPlaybackRate() == 0.0f
) {
173 // Output silence if stopped.
174 for (size_t i
= 0; i
< audio_data
.size(); ++i
)
175 memset(audio_data
[i
], 0, sizeof(float) * number_of_frames
);
179 // Adjust the playback delay.
180 base::TimeDelta request_delay
=
181 base::TimeDelta::FromMilliseconds(audio_delay_milliseconds
);
183 // Finally we need to adjust the delay according to playback rate.
184 if (GetPlaybackRate() != 1.0f
) {
185 request_delay
= base::TimeDelta::FromMicroseconds(
186 static_cast<int64
>(ceil(request_delay
.InMicroseconds() *
187 GetPlaybackRate())));
190 int bytes_per_frame
= audio_parameters_
.GetBytesPerFrame();
192 const size_t buf_size
= number_of_frames
* bytes_per_frame
;
193 scoped_array
<uint8
> buf(new uint8
[buf_size
]);
195 uint32 frames_filled
= FillBuffer(buf
.get(), number_of_frames
, request_delay
);
196 uint32 bytes_filled
= frames_filled
* bytes_per_frame
;
197 DCHECK_LE(bytes_filled
, buf_size
);
198 UpdateEarliestEndTime(bytes_filled
, request_delay
, base::Time::Now());
200 // Deinterleave each audio channel.
201 int channels
= audio_data
.size();
202 for (int channel_index
= 0; channel_index
< channels
; ++channel_index
) {
203 media::DeinterleaveAudioChannel(buf
.get(),
204 audio_data
[channel_index
],
207 bytes_per_frame
/ channels
,
210 // If FillBuffer() didn't give us enough data then zero out the remainder.
211 if (frames_filled
< number_of_frames
) {
212 int frames_to_zero
= number_of_frames
- frames_filled
;
213 memset(audio_data
[channel_index
] + frames_filled
,
215 sizeof(float) * frames_to_zero
);
218 return frames_filled
;
221 void AudioRendererImpl::OnRenderError() {
222 host()->DisableAudioRenderer();
225 void AudioRendererImpl::OnRenderEndOfStream() {
226 // TODO(enal): schedule callback instead of polling.
227 if (base::Time::Now() >= earliest_end_time_
)