summaryrefslogtreecommitdiffstats
path: root/content/renderer/media/audio_renderer_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'content/renderer/media/audio_renderer_impl.cc')
-rw-r--r--content/renderer/media/audio_renderer_impl.cc52
1 files changed, 44 insertions, 8 deletions
diff --git a/content/renderer/media/audio_renderer_impl.cc b/content/renderer/media/audio_renderer_impl.cc
index 14643ab..899bf44 100644
--- a/content/renderer/media/audio_renderer_impl.cc
+++ b/content/renderer/media/audio_renderer_impl.cc
@@ -6,13 +6,17 @@
#include <math.h>
-#include "content/common/child_process.h"
+#include <algorithm>
+
#include "base/command_line.h"
+#include "content/common/child_process.h"
#include "content/common/content_switches.h"
#include "content/common/media/audio_messages.h"
#include "content/renderer/render_thread.h"
#include "content/renderer/render_view.h"
+#include "media/audio/audio_buffers_state.h"
#include "media/audio/audio_output_controller.h"
+#include "media/audio/audio_util.h"
#include "media/base/filter_host.h"
// Static variable that says what code path we are using -- low or high
@@ -62,6 +66,23 @@ base::TimeDelta AudioRendererImpl::ConvertToDuration(int bytes) {
return base::TimeDelta();
}
+void AudioRendererImpl::UpdateEarliestEndTime(int bytes_filled,
+ base::TimeDelta request_delay,
+ base::Time time_now) {
+ if (bytes_filled != 0) {
+ base::TimeDelta predicted_play_time = ConvertToDuration(bytes_filled);
+ float playback_rate = GetPlaybackRate();
+ if (playback_rate != 1.0f) {
+ predicted_play_time = base::TimeDelta::FromMicroseconds(
+ static_cast<int64>(ceil(predicted_play_time.InMicroseconds() *
+ playback_rate)));
+ }
+ earliest_end_time_ =
+ std::max(earliest_end_time_,
+ time_now + request_delay + predicted_play_time);
+ }
+}
+
bool AudioRendererImpl::OnInitialize(const media::AudioDecoderConfig& config) {
AudioParameters params(config);
params.format = AudioParameters::AUDIO_PCM_LINEAR;
@@ -244,7 +265,7 @@ void AudioRendererImpl::OnLowLatencyCreated(
return;
shared_memory_.reset(new base::SharedMemory(handle, false));
- shared_memory_->Map(length);
+ shared_memory_->Map(media::TotalSharedMemorySizeInBytes(length));
shared_memory_size_ = length;
CreateSocket(socket_handle);
@@ -320,6 +341,7 @@ void AudioRendererImpl::CreateStreamTask(const AudioParameters& audio_params) {
void AudioRendererImpl::PlayTask() {
DCHECK(MessageLoop::current() == ChildProcess::current()->io_message_loop());
+ earliest_end_time_ = base::Time::Now();
Send(new AudioHostMsg_PlayStream(stream_id_));
}
@@ -332,6 +354,7 @@ void AudioRendererImpl::PauseTask() {
void AudioRendererImpl::SeekTask() {
DCHECK(MessageLoop::current() == ChildProcess::current()->io_message_loop());
+ earliest_end_time_ = base::Time::Now();
// We have to pause the audio stream before we can flush.
Send(new AudioHostMsg_PauseStream(stream_id_));
Send(new AudioHostMsg_FlushStream(stream_id_));
@@ -396,10 +419,18 @@ void AudioRendererImpl::NotifyPacketReadyTask() {
GetPlaybackRate())));
}
+ bool buffer_empty = (request_buffers_state_.pending_bytes == 0) &&
+ (current_time >= earliest_end_time_);
+
+ // For high latency mode we don't write length into shared memory,
+ // it is explicit part of AudioHostMsg_NotifyPacketReady() message,
+ // so no need to reserve first word of buffer for length.
uint32 filled = FillBuffer(static_cast<uint8*>(shared_memory_->memory()),
shared_memory_size_, request_delay,
- request_buffers_state_.pending_bytes == 0);
+ buffer_empty);
+ UpdateEarliestEndTime(filled, request_delay, current_time);
pending_request_ = false;
+
// Then tell browser process we are done filling into the buffer.
Send(new AudioHostMsg_NotifyPacketReady(stream_id_, filled));
}
@@ -426,7 +457,6 @@ void AudioRendererImpl::Run() {
int bytes;
while (sizeof(bytes) == socket_->Receive(&bytes, sizeof(bytes))) {
- LOG(ERROR) << "+++ bytes: " << bytes;
if (bytes == media::AudioOutputController::kPauseMark)
continue;
else if (bytes < 0)
@@ -439,16 +469,22 @@ void AudioRendererImpl::Run() {
continue;
DCHECK(shared_memory_.get());
base::TimeDelta request_delay = ConvertToDuration(bytes);
+
// We need to adjust the delay according to playback rate.
if (playback_rate != 1.0f) {
request_delay = base::TimeDelta::FromMicroseconds(
static_cast<int64>(ceil(request_delay.InMicroseconds() *
playback_rate)));
}
- FillBuffer(static_cast<uint8*>(shared_memory_->memory()),
- shared_memory_size_,
- request_delay,
- true /* buffers empty */);
+ base::Time time_now = base::Time::Now();
+ uint32 size = FillBuffer(static_cast<uint8*>(shared_memory_->memory()),
+ shared_memory_size_,
+ request_delay,
+ time_now >= earliest_end_time_);
+ media::SetActualDataSizeInBytes(shared_memory_.get(),
+ shared_memory_size_,
+ size);
+ UpdateEarliestEndTime(size, request_delay, time_now);
}
}