Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 #ifndef REMOTING_HOST_AUDIO_CAPTURER_LINUX_H_ | 5 #ifndef REMOTING_HOST_AUDIO_CAPTURER_LINUX_H_ |
| 6 #define REMOTING_HOST_AUDIO_CAPTURER_LINUX_H_ | 6 #define REMOTING_HOST_AUDIO_CAPTURER_LINUX_H_ |
| 7 | 7 |
| 8 #include "remoting/host/audio_capturer.h" | 8 #include "base/memory/ref_counted_memory.h" |
| 9 | |
| 10 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/observer_list_threadsafe.h" | |
| 11 #include "base/time.h" | 11 #include "base/time.h" |
| 12 #include "base/timer.h" | 12 #include "base/timer.h" |
| 13 #include "remoting/host/audio_capturer.h" | |
| 13 | 14 |
| 14 class FilePath; | 15 class FilePath; |
| 15 | 16 |
| 16 namespace remoting { | 17 namespace remoting { |
| 17 | 18 |
| 18 class AudioCapturerLinux : public AudioCapturer, | 19 class AudioCapturerLinux; |
| 19 public MessageLoopForIO::Watcher { | 20 |
| 21 // On Linux audio capturer is implemented by redirecting audio stream from | |
| 22 // pulseaudio to the host process via a named pipe. The daemon that starts the | |
| 23 // host sets up pulseaudio environment variables and writes config for it such | |
| 24 // that pulseaudio uses module-pipe-sink for all playback streams. | |
| 25 // AudioCapturerLinuxCore class reads from the pipe and then sends data to all | |
| 26 // instances of AudioCapturerLinux. This is necessary because we need to read | |
| 27 // from the pipe even when there are no active Chromoting clients. Otherwise | |
| 28 // pulseaudio would block all playback streams. | |
|
Wez
2012/10/30 04:20:11
Can we reword this comment to describe the roles o
Sergey Ulanov
2012/10/30 23:59:48
Done.
| |
| 29 class AudioCapturerLinuxCore | |
|
Wez
2012/10/30 04:20:11
nit: Since this class is effectively the sink for
Sergey Ulanov
2012/10/30 23:59:48
Good idea. Renamed it to PulseaudioPipeSinkReader
Wez
2012/10/31 00:56:27
nit: If this class would work with _any_ pipe-base
| |
| 30 : public base::RefCountedThreadSafe<AudioCapturerLinuxCore>, | |
|
Wez
2012/10/30 04:20:11
Does this need to be ref-counted? When will we ev
Sergey Ulanov
2012/10/30 23:59:48
We should try to avoid global variables. Ideally t
| |
| 31 public MessageLoopForIO::Watcher { | |
| 20 public: | 32 public: |
| 21 // Must be called to configure the capturer before the first instance is | 33 // Must be called to configure the capturer before the first capturer instance |
| 22 // created. | 34 // is created. |
| 23 static void SetPipeName(const FilePath& pipe_name); | 35 static void Initialize( |
| 36 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | |
|
Wez
2012/10/30 04:20:11
nit: Clarify the role of |task_runner|.
Sergey Ulanov
2012/10/30 23:59:48
Done.
| |
| 37 const FilePath& pipe_name); | |
| 24 | 38 |
| 25 explicit AudioCapturerLinux(const FilePath& pipe_name); | 39 explicit AudioCapturerLinuxCore( |
|
Wez
2012/10/30 04:20:11
nit: Don't need explicit here.
Wez
2012/10/30 04:20:11
Does the ctor need to be public?
Sergey Ulanov
2012/10/30 23:59:48
Done.
Sergey Ulanov
2012/10/30 23:59:48
Done.
| |
| 26 virtual ~AudioCapturerLinux(); | 40 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| 41 const FilePath& pipe_name); | |
| 27 | 42 |
| 28 // AudioCapturer interface. | 43 // AudioCapturer interface. |
|
Wez
2012/10/30 04:20:11
nit: This isn't the AudioCapturer interface. :)
Sergey Ulanov
2012/10/30 23:59:48
Done.
| |
| 29 virtual bool Start(const PacketCapturedCallback& callback) OVERRIDE; | 44 void AddCapturer(AudioCapturerLinux* capturer); |
| 30 virtual void Stop() OVERRIDE; | 45 void RemoveCapturer(AudioCapturerLinux* capturer); |
| 31 virtual bool IsStarted() OVERRIDE; | |
| 32 | 46 |
| 33 // MessageLoopForIO::Watcher interface. | 47 // MessageLoopForIO::Watcher interface. |
| 34 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; | 48 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; |
| 35 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; | 49 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; |
| 36 | 50 |
| 37 private: | 51 private: |
| 52 friend class base::RefCountedThreadSafe<AudioCapturerLinuxCore>; | |
| 53 virtual ~AudioCapturerLinuxCore(); | |
| 54 | |
| 55 void StartReading(const FilePath& pipe_name); | |
|
Wez
2012/10/30 04:20:11
nit: Suggest renaming to StartOnCaptureThread.
Wez
2012/10/30 04:20:11
nit: Do you really need to pass |pipe_name|, rathe
Sergey Ulanov
2012/10/30 23:59:48
We need to use this name only once, so there is no
Sergey Ulanov
2012/10/30 23:59:48
Renamed to StartOnAudioThread().
| |
| 38 void StartTimer(); | 56 void StartTimer(); |
| 39 void DoCapture(); | 57 void DoCapture(); |
| 40 void WaitForPipeReadable(); | 58 void WaitForPipeReadable(); |
| 41 | 59 |
| 60 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; | |
|
Wez
2012/10/30 04:20:11
nit: Name this something more helpful, e.g. |captu
Sergey Ulanov
2012/10/30 23:59:48
It's unambiguous as there is only one thread this
| |
| 61 | |
| 42 int pipe_fd_; | 62 int pipe_fd_; |
| 43 base::RepeatingTimer<AudioCapturerLinux> timer_; | 63 base::RepeatingTimer<AudioCapturerLinuxCore> timer_; |
| 44 PacketCapturedCallback callback_; | 64 scoped_refptr<ObserverListThreadSafe<AudioCapturerLinux> > capturers_; |
| 45 | 65 |
| 46 // Time when capturing was started. | 66 // Time when capturing was started. |
| 47 base::TimeTicks started_time_; | 67 base::TimeTicks started_time_; |
| 48 | 68 |
| 49 // Stream position of the last capture. | 69 // Stream position of the last capture. |
| 50 int64 last_capture_samples_; | 70 int64 last_capture_samples_; |
| 51 | 71 |
| 52 // Bytes left from the previous read. | 72 // Bytes left from the previous read. |
| 53 std::string left_over_bytes_; | 73 std::string left_over_bytes_; |
| 54 | 74 |
| 55 MessageLoopForIO::FileDescriptorWatcher file_descriptor_watcher_; | 75 MessageLoopForIO::FileDescriptorWatcher file_descriptor_watcher_; |
| 56 | 76 |
| 77 DISALLOW_COPY_AND_ASSIGN(AudioCapturerLinuxCore); | |
| 78 }; | |
| 79 | |
| 80 class AudioCapturerLinux : public AudioCapturer { | |
| 81 public: | |
| 82 explicit AudioCapturerLinux(scoped_refptr<AudioCapturerLinuxCore> core); | |
|
Wez
2012/10/30 04:20:11
nit: Do you need to pass |core| in here? Can't yo
Sergey Ulanov
2012/10/30 23:59:48
In the future I'd like to avoid the need to have t
| |
| 83 virtual ~AudioCapturerLinux(); | |
| 84 | |
| 85 // AudioCapturer interface. | |
| 86 virtual bool Start(const PacketCapturedCallback& callback) OVERRIDE; | |
| 87 virtual void Stop() OVERRIDE; | |
| 88 virtual bool IsStarted() OVERRIDE; | |
| 89 | |
| 90 private: | |
| 91 friend class AudioCapturerLinuxCore; | |
| 92 | |
| 93 // Called by AudioCapturerLinuxCore; | |
| 94 void OnDataRead(scoped_refptr<base::RefCountedString> data); | |
| 95 | |
| 96 scoped_refptr<AudioCapturerLinuxCore> core_; | |
| 97 PacketCapturedCallback callback_; | |
| 98 | |
| 57 DISALLOW_COPY_AND_ASSIGN(AudioCapturerLinux); | 99 DISALLOW_COPY_AND_ASSIGN(AudioCapturerLinux); |
| 58 }; | 100 }; |
| 59 | 101 |
| 60 } // namespace remoting | 102 } // namespace remoting |
| 61 | 103 |
| 62 #endif // REMOTING_HOST_AUDIO_CAPTURER_LINUX_H_ | 104 #endif // REMOTING_HOST_AUDIO_CAPTURER_LINUX_H_ |
| OLD | NEW |