summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/media/audio_renderer_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/renderer/media/audio_renderer_impl.cc')
-rw-r--r--chrome/renderer/media/audio_renderer_impl.cc60
1 files changed, 49 insertions, 11 deletions
diff --git a/chrome/renderer/media/audio_renderer_impl.cc b/chrome/renderer/media/audio_renderer_impl.cc
index 9dd365c..73f2320 100644
--- a/chrome/renderer/media/audio_renderer_impl.cc
+++ b/chrome/renderer/media/audio_renderer_impl.cc
@@ -28,14 +28,18 @@ const int kMillisecondsPreroll = 400;
AudioRendererImpl::AudioRendererImpl(AudioMessageFilter* filter)
: AudioRendererBase(kDefaultMaxQueueSize),
+ channels_(0),
+ sample_rate_(0),
+ sample_bits_(0),
+ bytes_per_second_(0),
filter_(filter),
stream_id_(0),
shared_memory_(NULL),
shared_memory_size_(0),
io_loop_(filter->message_loop()),
stopped_(false),
- pending_request_(false),
playback_rate_(0.0f),
+ pending_request_(false),
prerolling_(true),
preroll_bytes_(0) {
DCHECK(io_loop_);
@@ -44,6 +48,14 @@ AudioRendererImpl::AudioRendererImpl(AudioMessageFilter* filter)
AudioRendererImpl::~AudioRendererImpl() {
}
+base::TimeDelta AudioRendererImpl::ConvertToDuration(int bytes) {
+ if (bytes_per_second_) {
+ return base::TimeDelta::FromMicroseconds(
+ base::Time::kMicrosecondsPerSecond * bytes / bytes_per_second_);
+ }
+ return base::TimeDelta();
+}
+
bool AudioRendererImpl::IsMediaFormatSupported(
const media::MediaFormat& media_format) {
int channels;
@@ -54,24 +66,24 @@ bool AudioRendererImpl::IsMediaFormatSupported(
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)) {
+ if (!ParseMediaFormat(media_format,
+ &channels_,
+ &sample_rate_,
+ &sample_bits_)) {
return false;
}
// Create the audio output stream in browser process.
- size_t bytes_per_second = sample_rate * channels * sample_bits / 8;
- size_t packet_size = bytes_per_second * kMillisecondsPerPacket / 1000;
+ bytes_per_second_ = sample_rate_ * channels_ * sample_bits_ / 8;
+ size_t packet_size = bytes_per_second_ * kMillisecondsPerPacket / 1000;
size_t buffer_capacity = packet_size * kPacketsInBuffer;
// Calculate the amount for prerolling.
- preroll_bytes_ = bytes_per_second * kMillisecondsPreroll / 1000;
+ preroll_bytes_ = bytes_per_second_ * kMillisecondsPreroll / 1000;
io_loop_->PostTask(FROM_HERE,
NewRunnableMethod(this, &AudioRendererImpl::OnCreateStream,
- AudioManager::AUDIO_PCM_LINEAR, channels, sample_rate, sample_bits,
+ AudioManager::AUDIO_PCM_LINEAR, channels_, sample_rate_, sample_bits_,
packet_size, buffer_capacity));
return true;
}
@@ -153,13 +165,19 @@ void AudioRendererImpl::OnCreated(base::SharedMemoryHandle handle,
shared_memory_size_ = length;
}
-void AudioRendererImpl::OnRequestPacket() {
+void AudioRendererImpl::OnRequestPacket(size_t bytes_in_buffer,
+ const base::Time& message_timestamp) {
DCHECK(MessageLoop::current() == io_loop_);
{
AutoLock auto_lock(lock_);
DCHECK(!pending_request_);
pending_request_ = true;
+
+ // Use the information provided by the IPC message to adjust the playback
+ // delay.
+ request_timestamp_ = message_timestamp;
+ request_delay_ = ConvertToDuration(bytes_in_buffer);
}
// Try to fill in the fulfil the packet request.
@@ -253,12 +271,32 @@ void AudioRendererImpl::OnNotifyPacketReady() {
return;
if (pending_request_ && playback_rate_ > 0.0f) {
DCHECK(shared_memory_.get());
+
+ // Adjust the playback delay.
+ base::Time current_time = base::Time::Now();
+
+ // Save a local copy of the request delay.
+ base::TimeDelta request_delay = request_delay_;
+ if (current_time > request_timestamp_) {
+ base::TimeDelta receive_latency = current_time - request_timestamp_;
+
+ // If the receive latency is too much it may offset all the delay.
+ if (receive_latency >= request_delay) {
+ request_delay = base::TimeDelta();
+ } else {
+ request_delay -= receive_latency;
+ }
+ }
+
size_t filled = FillBuffer(static_cast<uint8*>(shared_memory_->memory()),
shared_memory_size_,
- playback_rate_);
+ playback_rate_,
+ request_delay);
// TODO(hclam): we should try to fill in the buffer as much as possible.
if (filled > 0) {
pending_request_ = false;
+ request_delay_ = base::TimeDelta();
+ request_timestamp_ = base::Time();
// Then tell browser process we are done filling into the buffer.
filter_->Send(
new ViewHostMsg_NotifyAudioPacketReady(0, stream_id_, filled));