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

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 6 years 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 pipe_buffer_size_ = fpathconf(pipe_.GetPlatformFile(), _PC_PIPE_BUF);
Lambros 2014/12/23 23:07:18 I don't think this call can fail, can it?
Sergey Ulanov 2014/12/24 00:01:28 it shouldn't, but it's still better to check if it
141 if (HANDLE_EINTR(fcntl( 131 capture_period_ = base::TimeDelta::FromSeconds(1) * pipe_buffer_size_ /
142 pipe_.GetPlatformFile(), F_SETPIPE_SZ, kPipeBufferSizeBytes)) < 0) { 132 kSampleBytesPerSecond / 2;
Lambros 2014/12/23 23:07:18 I'm curious to know why we divide by 2? Is it simp
Sergey Ulanov 2014/12/24 00:01:26 Yes. We need to capture more often than the buffer
143 PLOG(ERROR) << "fcntl";
144 }
145 133
146 WaitForPipeReadable(); 134 WaitForPipeReadable();
147 } 135 }
148 } 136 }
149 137
150 void AudioPipeReader::StartTimer() { 138 void AudioPipeReader::StartTimer() {
151 DCHECK(task_runner_->BelongsToCurrentThread()); 139 DCHECK(task_runner_->BelongsToCurrentThread());
152 started_time_ = base::TimeTicks::Now(); 140 started_time_ = base::TimeTicks::Now();
153 last_capture_position_ = 0; 141 last_capture_position_ = 0;
154 timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kCapturingPeriodMs), 142 timer_.Start(FROM_HERE, capture_period_, this, &AudioPipeReader::DoCapture);
155 this, &AudioPipeReader::DoCapture);
156 } 143 }
157 144
158 void AudioPipeReader::DoCapture() { 145 void AudioPipeReader::DoCapture() {
159 DCHECK(task_runner_->BelongsToCurrentThread()); 146 DCHECK(task_runner_->BelongsToCurrentThread());
160 DCHECK(pipe_.IsValid()); 147 DCHECK(pipe_.IsValid());
161 148
162 // Calculate how much we need read from the pipe. Pulseaudio doesn't control 149 // 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. 150 // 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_; 151 base::TimeDelta stream_position = base::TimeTicks::Now() - started_time_;
165 int64 stream_position_bytes = stream_position.InMilliseconds() * 152 int64 stream_position_bytes = stream_position.InMilliseconds() *
(...skipping 28 matching lines...) Expand all
194 int incomplete_samples_bytes = pos % (kChannels * kBytesPerSample); 181 int incomplete_samples_bytes = pos % (kChannels * kBytesPerSample);
195 left_over_bytes_.assign(data, pos - incomplete_samples_bytes, 182 left_over_bytes_.assign(data, pos - incomplete_samples_bytes,
196 incomplete_samples_bytes); 183 incomplete_samples_bytes);
197 data.resize(pos - incomplete_samples_bytes); 184 data.resize(pos - incomplete_samples_bytes);
198 185
199 last_capture_position_ += data.size(); 186 last_capture_position_ += data.size();
200 // Normally PulseAudio will keep pipe buffer full, so we should always be able 187 // 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 188 // 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 189 // sure that |stream_position_bytes| doesn't go out of sync with the current
203 // stream position. 190 // stream position.
204 if (stream_position_bytes - last_capture_position_ > kPipeBufferSizeBytes) 191 if (stream_position_bytes - last_capture_position_ > pipe_buffer_size_)
205 last_capture_position_ = stream_position_bytes - kPipeBufferSizeBytes; 192 last_capture_position_ = stream_position_bytes - pipe_buffer_size_;
206 DCHECK_LE(last_capture_position_, stream_position_bytes); 193 DCHECK_LE(last_capture_position_, stream_position_bytes);
207 194
208 // Dispatch asynchronous notification to the stream observers. 195 // Dispatch asynchronous notification to the stream observers.
209 scoped_refptr<base::RefCountedString> data_ref = 196 scoped_refptr<base::RefCountedString> data_ref =
210 base::RefCountedString::TakeString(&data); 197 base::RefCountedString::TakeString(&data);
211 observers_->Notify(&StreamObserver::OnDataRead, data_ref); 198 observers_->Notify(&StreamObserver::OnDataRead, data_ref);
212 } 199 }
213 200
214 void AudioPipeReader::WaitForPipeReadable() { 201 void AudioPipeReader::WaitForPipeReadable() {
215 timer_.Stop(); 202 timer_.Stop();
216 base::MessageLoopForIO::current()->WatchFileDescriptor( 203 base::MessageLoopForIO::current()->WatchFileDescriptor(
217 pipe_.GetPlatformFile(), false, base::MessageLoopForIO::WATCH_READ, 204 pipe_.GetPlatformFile(), false, base::MessageLoopForIO::WATCH_READ,
218 &file_descriptor_watcher_, this); 205 &file_descriptor_watcher_, this);
219 } 206 }
220 207
221 // static 208 // static
222 void AudioPipeReaderTraits::Destruct(const AudioPipeReader* audio_pipe_reader) { 209 void AudioPipeReaderTraits::Destruct(const AudioPipeReader* audio_pipe_reader) {
223 audio_pipe_reader->task_runner_->DeleteSoon(FROM_HERE, audio_pipe_reader); 210 audio_pipe_reader->task_runner_->DeleteSoon(FROM_HERE, audio_pipe_reader);
224 } 211 }
225 212
226 } // namespace remoting 213 } // 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