OLD | NEW |
| (Empty) |
1 // Copyright 2015 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. | |
4 | |
5 #include "remoting/host/audio_pump.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/location.h" | |
11 #include "base/logging.h" | |
12 #include "base/macros.h" | |
13 #include "base/single_thread_task_runner.h" | |
14 #include "base/threading/thread_task_runner_handle.h" | |
15 #include "remoting/codec/audio_encoder.h" | |
16 #include "remoting/host/audio_capturer.h" | |
17 #include "remoting/proto/audio.pb.h" | |
18 #include "remoting/protocol/audio_stub.h" | |
19 | |
20 namespace remoting { | |
21 | |
22 // Limit the data stored in the pending send buffers to 250ms. | |
23 const int kMaxBufferedIntervalMs = 250; | |
24 | |
25 class AudioPump::Core { | |
26 public: | |
27 Core(base::WeakPtr<AudioPump> pump, | |
28 std::unique_ptr<AudioCapturer> audio_capturer, | |
29 std::unique_ptr<AudioEncoder> audio_encoder); | |
30 ~Core(); | |
31 | |
32 void Start(); | |
33 void Pause(bool pause); | |
34 | |
35 void OnPacketSent(int size); | |
36 | |
37 private: | |
38 void EncodeAudioPacket(std::unique_ptr<AudioPacket> packet); | |
39 | |
40 base::ThreadChecker thread_checker_; | |
41 | |
42 base::WeakPtr<AudioPump> pump_; | |
43 | |
44 scoped_refptr<base::SingleThreadTaskRunner> pump_task_runner_; | |
45 | |
46 std::unique_ptr<AudioCapturer> audio_capturer_; | |
47 std::unique_ptr<AudioEncoder> audio_encoder_; | |
48 | |
49 bool enabled_; | |
50 | |
51 // Number of bytes in the queue that have been encoded but haven't been sent | |
52 // yet. | |
53 int bytes_pending_; | |
54 | |
55 DISALLOW_COPY_AND_ASSIGN(Core); | |
56 }; | |
57 | |
58 AudioPump::Core::Core(base::WeakPtr<AudioPump> pump, | |
59 std::unique_ptr<AudioCapturer> audio_capturer, | |
60 std::unique_ptr<AudioEncoder> audio_encoder) | |
61 : pump_(pump), | |
62 pump_task_runner_(base::ThreadTaskRunnerHandle::Get()), | |
63 audio_capturer_(std::move(audio_capturer)), | |
64 audio_encoder_(std::move(audio_encoder)), | |
65 enabled_(true), | |
66 bytes_pending_(0) { | |
67 thread_checker_.DetachFromThread(); | |
68 } | |
69 | |
70 AudioPump::Core::~Core() { | |
71 DCHECK(thread_checker_.CalledOnValidThread()); | |
72 } | |
73 | |
74 void AudioPump::Core::Start() { | |
75 DCHECK(thread_checker_.CalledOnValidThread()); | |
76 | |
77 audio_capturer_->Start( | |
78 base::Bind(&Core::EncodeAudioPacket, base::Unretained(this))); | |
79 } | |
80 | |
81 void AudioPump::Core::Pause(bool pause) { | |
82 DCHECK(thread_checker_.CalledOnValidThread()); | |
83 | |
84 enabled_ = !pause; | |
85 } | |
86 | |
87 void AudioPump::Core::OnPacketSent(int size) { | |
88 DCHECK(thread_checker_.CalledOnValidThread()); | |
89 | |
90 bytes_pending_-= size; | |
91 DCHECK_GE(bytes_pending_, 0); | |
92 } | |
93 | |
94 void AudioPump::Core::EncodeAudioPacket(std::unique_ptr<AudioPacket> packet) { | |
95 DCHECK(thread_checker_.CalledOnValidThread()); | |
96 DCHECK(packet); | |
97 | |
98 int max_buffered_bytes = | |
99 audio_encoder_->GetBitrate() * kMaxBufferedIntervalMs / 1000 / 8; | |
100 if (!enabled_ || bytes_pending_ > max_buffered_bytes) | |
101 return; | |
102 | |
103 std::unique_ptr<AudioPacket> encoded_packet = | |
104 audio_encoder_->Encode(std::move(packet)); | |
105 | |
106 // The audio encoder returns a null audio packet if there's no audio to send. | |
107 if (!encoded_packet) | |
108 return; | |
109 | |
110 int packet_size = encoded_packet->ByteSize(); | |
111 bytes_pending_ += packet_size; | |
112 | |
113 pump_task_runner_->PostTask( | |
114 FROM_HERE, base::Bind(&AudioPump::SendAudioPacket, pump_, | |
115 base::Passed(&encoded_packet), packet_size)); | |
116 } | |
117 | |
118 AudioPump::AudioPump( | |
119 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner, | |
120 std::unique_ptr<AudioCapturer> audio_capturer, | |
121 std::unique_ptr<AudioEncoder> audio_encoder, | |
122 protocol::AudioStub* audio_stub) | |
123 : audio_task_runner_(audio_task_runner), | |
124 audio_stub_(audio_stub), | |
125 weak_factory_(this) { | |
126 DCHECK(audio_stub_); | |
127 | |
128 core_.reset(new Core(weak_factory_.GetWeakPtr(), std::move(audio_capturer), | |
129 std::move(audio_encoder))); | |
130 | |
131 audio_task_runner_->PostTask( | |
132 FROM_HERE, base::Bind(&Core::Start, base::Unretained(core_.get()))); | |
133 } | |
134 | |
135 AudioPump::~AudioPump() { | |
136 DCHECK(thread_checker_.CalledOnValidThread()); | |
137 | |
138 audio_task_runner_->DeleteSoon(FROM_HERE, core_.release()); | |
139 } | |
140 | |
141 void AudioPump::Pause(bool pause) { | |
142 DCHECK(thread_checker_.CalledOnValidThread()); | |
143 | |
144 audio_task_runner_->PostTask( | |
145 FROM_HERE, | |
146 base::Bind(&Core::Pause, base::Unretained(core_.get()), pause)); | |
147 } | |
148 | |
149 void AudioPump::SendAudioPacket(std::unique_ptr<AudioPacket> packet, int size) { | |
150 DCHECK(thread_checker_.CalledOnValidThread()); | |
151 DCHECK(packet); | |
152 | |
153 audio_stub_->ProcessAudioPacket( | |
154 std::move(packet), | |
155 base::Bind(&AudioPump::OnPacketSent, weak_factory_.GetWeakPtr(), size)); | |
156 } | |
157 | |
158 void AudioPump::OnPacketSent(int size) { | |
159 audio_task_runner_->PostTask( | |
160 FROM_HERE, | |
161 base::Bind(&Core::OnPacketSent, base::Unretained(core_.get()), size)); | |
162 } | |
163 | |
164 } // namespace remoting | |
OLD | NEW |