Save errno for logging before potentially overwriting it.
[chromium-blink-merge.git] / content / browser / renderer_host / media / audio_sync_reader.cc
blob39fc80d1e55cc9ba15b347cdbd55d6ede24c586e
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/browser/renderer_host/media/audio_sync_reader.h"
7 #include <algorithm>
9 #include "base/metrics/histogram.h"
10 #include "base/process_util.h"
11 #include "base/shared_memory.h"
12 #include "media/audio/audio_buffers_state.h"
13 #include "media/audio/audio_parameters.h"
14 #include "media/audio/shared_memory_util.h"
16 using media::AudioBus;
18 namespace content {
20 AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory,
21 const media::AudioParameters& params,
22 int input_channels)
23 : shared_memory_(shared_memory),
24 input_channels_(input_channels),
25 renderer_callback_count_(0),
26 renderer_missed_callback_count_(0) {
27 packet_size_ = media::PacketSizeInBytes(shared_memory_->requested_size());
28 int input_memory_size = 0;
29 int output_memory_size = AudioBus::CalculateMemorySize(params);
30 if (input_channels_ > 0) {
31 // The input storage is after the output storage.
32 int frames = params.frames_per_buffer();
33 input_memory_size = AudioBus::CalculateMemorySize(input_channels_, frames);
34 char* input_data =
35 static_cast<char*>(shared_memory_->memory()) + output_memory_size;
36 input_bus_ = AudioBus::WrapMemory(input_channels_, frames, input_data);
38 DCHECK_EQ(packet_size_, output_memory_size + input_memory_size);
39 output_bus_ = AudioBus::WrapMemory(params, shared_memory->memory());
42 AudioSyncReader::~AudioSyncReader() {
43 if (!renderer_callback_count_)
44 return;
46 // Recording the percentage of deadline misses gives us a rough overview of
47 // how many users might be running into audio glitches.
48 int percentage_missed =
49 100.0 * renderer_missed_callback_count_ / renderer_callback_count_;
50 UMA_HISTOGRAM_PERCENTAGE(
51 "Media.AudioRendererMissedDeadline", percentage_missed);
54 bool AudioSyncReader::DataReady() {
55 return !media::IsUnknownDataSize(shared_memory_, packet_size_);
58 // media::AudioOutputController::SyncReader implementations.
59 void AudioSyncReader::UpdatePendingBytes(uint32 bytes) {
60 if (bytes != static_cast<uint32>(media::kPauseMark)) {
61 // Store unknown length of data into buffer, so we later
62 // can find out if data became available.
63 media::SetUnknownDataSize(shared_memory_, packet_size_);
66 if (socket_) {
67 socket_->Send(&bytes, sizeof(bytes));
71 int AudioSyncReader::Read(bool block, const AudioBus* source, AudioBus* dest) {
72 ++renderer_callback_count_;
73 if (!DataReady()) {
74 ++renderer_missed_callback_count_;
76 if (block)
77 WaitTillDataReady();
80 // Copy optional synchronized live audio input for consumption by renderer
81 // process.
82 if (source && input_bus_) {
83 DCHECK_EQ(source->channels(), input_bus_->channels());
84 // TODO(crogers): In some cases with device and sample-rate changes
85 // it's possible for an AOR to insert a resampler in the path.
86 // Because this is used with the Web Audio API, it'd be better
87 // to bypass the device change handling in AOR and instead let
88 // the renderer-side Web Audio code deal with this.
89 if (source->frames() == input_bus_->frames() &&
90 source->channels() == input_bus_->channels())
91 source->CopyTo(input_bus_.get());
92 else
93 input_bus_->Zero();
96 // Retrieve the actual number of bytes available from the shared memory. If
97 // the renderer has not completed rendering this value will be invalid (still
98 // the marker stored in UpdatePendingBytes() above) and must be sanitized.
99 // TODO(dalecurtis): Technically this is not the exact size. Due to channel
100 // padding for alignment, there may be more data available than this; AudioBus
101 // will automatically do the right thing during CopyTo(). Rename this method
102 // to GetActualFrameCount().
103 uint32 size = media::GetActualDataSizeInBytes(shared_memory_, packet_size_);
105 // Compute the actual number of frames read. It's important to sanitize this
106 // value for a couple reasons. One, it might still be the unknown data size
107 // marker. Two, shared memory comes from a potentially untrusted source.
108 int frames =
109 size / (sizeof(*output_bus_->channel(0)) * output_bus_->channels());
110 if (frames < 0)
111 frames = 0;
112 else if (frames > output_bus_->frames())
113 frames = output_bus_->frames();
115 // Copy data from the shared memory into the caller's AudioBus.
116 output_bus_->CopyTo(dest);
118 // Zero out any unfilled frames in the destination bus.
119 dest->ZeroFramesPartial(frames, dest->frames() - frames);
121 // Zero out the entire output buffer to avoid stuttering/repeating-buffers
122 // in the anomalous case if the renderer is unable to keep up with real-time.
123 output_bus_->Zero();
125 // Store unknown length of data into buffer, in case renderer does not store
126 // the length itself. It also helps in decision if we need to yield.
127 media::SetUnknownDataSize(shared_memory_, packet_size_);
129 // Return the actual number of frames read.
130 return frames;
133 void AudioSyncReader::Close() {
134 if (socket_) {
135 socket_->Close();
139 bool AudioSyncReader::Init() {
140 socket_.reset(new base::CancelableSyncSocket());
141 foreign_socket_.reset(new base::CancelableSyncSocket());
142 return base::CancelableSyncSocket::CreatePair(socket_.get(),
143 foreign_socket_.get());
146 #if defined(OS_WIN)
147 bool AudioSyncReader::PrepareForeignSocketHandle(
148 base::ProcessHandle process_handle,
149 base::SyncSocket::Handle* foreign_handle) {
150 ::DuplicateHandle(GetCurrentProcess(), foreign_socket_->handle(),
151 process_handle, foreign_handle,
152 0, FALSE, DUPLICATE_SAME_ACCESS);
153 if (*foreign_handle != 0)
154 return true;
155 return false;
157 #else
158 bool AudioSyncReader::PrepareForeignSocketHandle(
159 base::ProcessHandle process_handle,
160 base::FileDescriptor* foreign_handle) {
161 foreign_handle->fd = foreign_socket_->handle();
162 foreign_handle->auto_close = false;
163 if (foreign_handle->fd != -1)
164 return true;
165 return false;
167 #endif
169 void AudioSyncReader::WaitTillDataReady() {
170 base::TimeTicks start = base::TimeTicks::Now();
171 const base::TimeDelta kMaxWait = base::TimeDelta::FromMilliseconds(20);
172 #if defined(OS_WIN)
173 // Sleep(0) on Windows lets the other threads run.
174 const base::TimeDelta kSleep = base::TimeDelta::FromMilliseconds(0);
175 #else
176 // We want to sleep for a bit here, as otherwise a backgrounded renderer won't
177 // get enough cpu to send the data and the high priority thread in the browser
178 // will use up a core causing even more skips.
179 const base::TimeDelta kSleep = base::TimeDelta::FromMilliseconds(2);
180 #endif
181 base::TimeDelta time_since_start;
182 do {
183 base::PlatformThread::Sleep(kSleep);
184 time_since_start = base::TimeTicks::Now() - start;
185 } while (!DataReady() && time_since_start < kMaxWait);
186 UMA_HISTOGRAM_CUSTOM_TIMES("Media.AudioOutputControllerDataNotReady",
187 time_since_start,
188 base::TimeDelta::FromMilliseconds(1),
189 base::TimeDelta::FromMilliseconds(1000),
190 50);
193 } // namespace content