Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(381)

Side by Side Diff: remoting/host/linux/audio_pipe_reader.cc

Issue 824943002: Fix AudioPipeReader to use default pipe buffer size. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « remoting/host/linux/audio_pipe_reader.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/linux/audio_pipe_reader.h" 5 #include "remoting/host/linux/audio_pipe_reader.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <sys/stat.h> 8 #include <sys/stat.h>
9 #include <sys/types.h> 9 #include <sys/types.h>
10 #include <unistd.h> 10 #include <unistd.h>
11 11
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/posix/eintr_wrapper.h" 13 #include "base/posix/eintr_wrapper.h"
14 #include "base/stl_util.h" 14 #include "base/stl_util.h"
15 15
16 namespace remoting { 16 namespace remoting {
17 17
18 namespace { 18 namespace {
19 19
20 const int kSampleBytesPerSecond = AudioPipeReader::kSamplingRate * 20 const int kSampleBytesPerSecond = AudioPipeReader::kSamplingRate *
21 AudioPipeReader::kChannels * 21 AudioPipeReader::kChannels *
22 AudioPipeReader::kBytesPerSample; 22 AudioPipeReader::kBytesPerSample;
23 23
24 // Read data from the pipe every 40ms.
25 const int kCapturingPeriodMs = 40;
26
27 // Size of the pipe buffer in milliseconds.
28 const int kPipeBufferSizeMs = kCapturingPeriodMs * 2;
29
30 // Size of the pipe buffer in bytes.
31 const int kPipeBufferSizeBytes = kPipeBufferSizeMs * kSampleBytesPerSecond /
32 base::Time::kMillisecondsPerSecond;
33
34 #if !defined(F_SETPIPE_SZ) 24 #if !defined(F_SETPIPE_SZ)
35 // F_SETPIPE_SZ is supported only starting linux 2.6.35, but we want to be able 25 // F_SETPIPE_SZ is supported only starting linux 2.6.35, but we want to be able
36 // to compile this code on machines with older kernel. 26 // to compile this code on machines with older kernel.
37 #define F_SETPIPE_SZ 1031 27 #define F_SETPIPE_SZ 1031
38 #endif // defined(F_SETPIPE_SZ) 28 #endif // defined(F_SETPIPE_SZ)
39 29
40 } // namespace 30 } // namespace
41 31
42 // static 32 // static
43 scoped_refptr<AudioPipeReader> AudioPipeReader::Create( 33 scoped_refptr<AudioPipeReader> AudioPipeReader::Create(
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 pipe_ = new_pipe.Pass(); 120 pipe_ = new_pipe.Pass();
131 121
132 if (pipe_.IsValid()) { 122 if (pipe_.IsValid()) {
133 // Set O_NONBLOCK flag. 123 // Set O_NONBLOCK flag.
134 if (HANDLE_EINTR(fcntl(pipe_.GetPlatformFile(), F_SETFL, O_NONBLOCK)) < 0) { 124 if (HANDLE_EINTR(fcntl(pipe_.GetPlatformFile(), F_SETFL, O_NONBLOCK)) < 0) {
135 PLOG(ERROR) << "fcntl"; 125 PLOG(ERROR) << "fcntl";
136 pipe_.Close(); 126 pipe_.Close();
137 return; 127 return;
138 } 128 }
139 129
140 // Set buffer size for the pipe. 130 // Get buffer size for the pipe.
141 if (HANDLE_EINTR(fcntl( 131 pipe_buffer_size_ = fpathconf(pipe_.GetPlatformFile(), _PC_PIPE_BUF);
142 pipe_.GetPlatformFile(), F_SETPIPE_SZ, kPipeBufferSizeBytes)) < 0) { 132 if (pipe_buffer_size_ < 0) {
143 PLOG(ERROR) << "fcntl"; 133 PLOG(ERROR) << "fpathconf(_PC_PIPE_BUF)";
134 pipe_buffer_size_ = 4096;
144 } 135 }
145 136
137 // Read from the pipe twice per buffer length, to avoid starving the stream.
138 capture_period_ = base::TimeDelta::FromSeconds(1) * pipe_buffer_size_ /
139 kSampleBytesPerSecond / 2;
140
146 WaitForPipeReadable(); 141 WaitForPipeReadable();
147 } 142 }
148 } 143 }
149 144
150 void AudioPipeReader::StartTimer() { 145 void AudioPipeReader::StartTimer() {
151 DCHECK(task_runner_->BelongsToCurrentThread()); 146 DCHECK(task_runner_->BelongsToCurrentThread());
152 started_time_ = base::TimeTicks::Now(); 147 started_time_ = base::TimeTicks::Now();
153 last_capture_position_ = 0; 148 last_capture_position_ = 0;
154 timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kCapturingPeriodMs), 149 timer_.Start(FROM_HERE, capture_period_, this, &AudioPipeReader::DoCapture);
155 this, &AudioPipeReader::DoCapture);
156 } 150 }
157 151
158 void AudioPipeReader::DoCapture() { 152 void AudioPipeReader::DoCapture() {
159 DCHECK(task_runner_->BelongsToCurrentThread()); 153 DCHECK(task_runner_->BelongsToCurrentThread());
160 DCHECK(pipe_.IsValid()); 154 DCHECK(pipe_.IsValid());
161 155
162 // Calculate how much we need read from the pipe. Pulseaudio doesn't control 156 // Calculate how much we need read from the pipe. Pulseaudio doesn't control
163 // how much data it writes to the pipe, so we need to pace the stream. 157 // how much data it writes to the pipe, so we need to pace the stream.
164 base::TimeDelta stream_position = base::TimeTicks::Now() - started_time_; 158 base::TimeDelta stream_position = base::TimeTicks::Now() - started_time_;
165 int64 stream_position_bytes = stream_position.InMilliseconds() * 159 int64 stream_position_bytes = stream_position.InMilliseconds() *
(...skipping 28 matching lines...) Expand all
194 int incomplete_samples_bytes = pos % (kChannels * kBytesPerSample); 188 int incomplete_samples_bytes = pos % (kChannels * kBytesPerSample);
195 left_over_bytes_.assign(data, pos - incomplete_samples_bytes, 189 left_over_bytes_.assign(data, pos - incomplete_samples_bytes,
196 incomplete_samples_bytes); 190 incomplete_samples_bytes);
197 data.resize(pos - incomplete_samples_bytes); 191 data.resize(pos - incomplete_samples_bytes);
198 192
199 last_capture_position_ += data.size(); 193 last_capture_position_ += data.size();
200 // Normally PulseAudio will keep pipe buffer full, so we should always be able 194 // Normally PulseAudio will keep pipe buffer full, so we should always be able
201 // to read |bytes_to_read| bytes, but in case it's misbehaving we need to make 195 // to read |bytes_to_read| bytes, but in case it's misbehaving we need to make
202 // sure that |stream_position_bytes| doesn't go out of sync with the current 196 // sure that |stream_position_bytes| doesn't go out of sync with the current
203 // stream position. 197 // stream position.
204 if (stream_position_bytes - last_capture_position_ > kPipeBufferSizeBytes) 198 if (stream_position_bytes - last_capture_position_ > pipe_buffer_size_)
205 last_capture_position_ = stream_position_bytes - kPipeBufferSizeBytes; 199 last_capture_position_ = stream_position_bytes - pipe_buffer_size_;
206 DCHECK_LE(last_capture_position_, stream_position_bytes); 200 DCHECK_LE(last_capture_position_, stream_position_bytes);
207 201
208 // Dispatch asynchronous notification to the stream observers. 202 // Dispatch asynchronous notification to the stream observers.
209 scoped_refptr<base::RefCountedString> data_ref = 203 scoped_refptr<base::RefCountedString> data_ref =
210 base::RefCountedString::TakeString(&data); 204 base::RefCountedString::TakeString(&data);
211 observers_->Notify(&StreamObserver::OnDataRead, data_ref); 205 observers_->Notify(&StreamObserver::OnDataRead, data_ref);
212 } 206 }
213 207
214 void AudioPipeReader::WaitForPipeReadable() { 208 void AudioPipeReader::WaitForPipeReadable() {
215 timer_.Stop(); 209 timer_.Stop();
216 base::MessageLoopForIO::current()->WatchFileDescriptor( 210 base::MessageLoopForIO::current()->WatchFileDescriptor(
217 pipe_.GetPlatformFile(), false, base::MessageLoopForIO::WATCH_READ, 211 pipe_.GetPlatformFile(), false, base::MessageLoopForIO::WATCH_READ,
218 &file_descriptor_watcher_, this); 212 &file_descriptor_watcher_, this);
219 } 213 }
220 214
221 // static 215 // static
222 void AudioPipeReaderTraits::Destruct(const AudioPipeReader* audio_pipe_reader) { 216 void AudioPipeReaderTraits::Destruct(const AudioPipeReader* audio_pipe_reader) {
223 audio_pipe_reader->task_runner_->DeleteSoon(FROM_HERE, audio_pipe_reader); 217 audio_pipe_reader->task_runner_->DeleteSoon(FROM_HERE, audio_pipe_reader);
224 } 218 }
225 219
226 } // namespace remoting 220 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/linux/audio_pipe_reader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698