OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/protocol/audio_pump.h" | 5 #include "remoting/protocol/audio_pump.h" |
6 | 6 |
| 7 #include <memory> |
7 #include <utility> | 8 #include <utility> |
8 | 9 |
9 #include "base/bind.h" | 10 #include "base/bind.h" |
10 #include "base/location.h" | 11 #include "base/location.h" |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/memory/ptr_util.h" |
13 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
14 #include "base/threading/thread_task_runner_handle.h" | 16 #include "base/threading/thread_task_runner_handle.h" |
| 17 #include "media/base/audio_bus.h" |
| 18 #include "media/base/audio_sample_types.h" |
| 19 #include "media/base/channel_layout.h" |
| 20 #include "media/base/channel_mixer.h" |
15 #include "remoting/codec/audio_encoder.h" | 21 #include "remoting/codec/audio_encoder.h" |
16 #include "remoting/proto/audio.pb.h" | 22 #include "remoting/proto/audio.pb.h" |
17 #include "remoting/protocol/audio_source.h" | 23 #include "remoting/protocol/audio_source.h" |
18 #include "remoting/protocol/audio_stub.h" | 24 #include "remoting/protocol/audio_stub.h" |
19 | 25 |
| 26 namespace { |
| 27 |
| 28 int CalculateFrameCount(const remoting::AudioPacket& packet) { |
| 29 return packet.data(0).size() / packet.channels() / packet.bytes_per_sample(); |
| 30 } |
| 31 |
| 32 std::unique_ptr<media::AudioBus> AudioPacketToAudioBus( |
| 33 const remoting::AudioPacket& packet) { |
| 34 const int frame_count = CalculateFrameCount(packet); |
| 35 if (frame_count < 1) { |
| 36 return nullptr; |
| 37 } |
| 38 |
| 39 std::unique_ptr<media::AudioBus> result = |
| 40 media::AudioBus::Create(packet.channels(), frame_count); |
| 41 result->FromInterleaved<media::SignedInt16SampleTypeTraits>( |
| 42 reinterpret_cast<const int16_t*>(packet.data(0).data()), frame_count); |
| 43 return result; |
| 44 } |
| 45 |
| 46 std::unique_ptr<remoting::AudioPacket> AudioBusToAudioPacket( |
| 47 const media::AudioBus& packet) { |
| 48 std::unique_ptr<remoting::AudioPacket> result = |
| 49 base::MakeUnique<remoting::AudioPacket>(); |
| 50 result->add_data()->resize( |
| 51 packet.channels() * packet.frames() * sizeof(int16_t)); |
| 52 packet.ToInterleaved<media::SignedInt16SampleTypeTraits>( |
| 53 packet.frames(), |
| 54 reinterpret_cast<int16_t*>(&(result->mutable_data(0)->at(0)))); |
| 55 result->set_encoding(remoting::AudioPacket::ENCODING_RAW); |
| 56 result->set_channels( |
| 57 static_cast<remoting::AudioPacket::Channels>(packet.channels())); |
| 58 result->set_bytes_per_sample(remoting::AudioPacket::BYTES_PER_SAMPLE_2); |
| 59 return result; |
| 60 } |
| 61 |
| 62 media::ChannelLayout RetrieveLayout(const remoting::AudioPacket& packet) { |
| 63 // This switch should match AudioPacket::Channels enum in audio.proto. |
| 64 switch (packet.channels()) { |
| 65 case remoting::AudioPacket::CHANNELS_INVALID: |
| 66 return media::CHANNEL_LAYOUT_UNSUPPORTED; |
| 67 case remoting::AudioPacket::CHANNELS_MONO: |
| 68 return media::CHANNEL_LAYOUT_MONO; |
| 69 case remoting::AudioPacket::CHANNELS_STEREO: |
| 70 return media::CHANNEL_LAYOUT_STEREO; |
| 71 case remoting::AudioPacket::CHANNELS_SURROUND: |
| 72 return media::CHANNEL_LAYOUT_SURROUND; |
| 73 case remoting::AudioPacket::CHANNELS_4_0: |
| 74 return media::CHANNEL_LAYOUT_4_0; |
| 75 case remoting::AudioPacket::CHANNELS_4_1: |
| 76 return media::CHANNEL_LAYOUT_4_1; |
| 77 case remoting::AudioPacket::CHANNELS_5_1: |
| 78 return media::CHANNEL_LAYOUT_5_1; |
| 79 case remoting::AudioPacket::CHANNELS_6_1: |
| 80 return media::CHANNEL_LAYOUT_6_1; |
| 81 case remoting::AudioPacket::CHANNELS_7_1: |
| 82 return media::CHANNEL_LAYOUT_7_1; |
| 83 } |
| 84 NOTREACHED() << "Invalid AudioPacket::Channels"; |
| 85 return media::CHANNEL_LAYOUT_UNSUPPORTED; |
| 86 } |
| 87 |
| 88 } // namespace |
| 89 |
20 namespace remoting { | 90 namespace remoting { |
21 namespace protocol { | 91 namespace protocol { |
22 | 92 |
23 // Limit the data stored in the pending send buffers to 250ms. | 93 // Limit the data stored in the pending send buffers to 250ms. |
24 const int kMaxBufferedIntervalMs = 250; | 94 const int kMaxBufferedIntervalMs = 250; |
25 | 95 |
26 class AudioPump::Core { | 96 class AudioPump::Core { |
27 public: | 97 public: |
28 Core(base::WeakPtr<AudioPump> pump, | 98 Core(base::WeakPtr<AudioPump> pump, |
29 std::unique_ptr<AudioSource> audio_source, | 99 std::unique_ptr<AudioSource> audio_source, |
30 std::unique_ptr<AudioEncoder> audio_encoder); | 100 std::unique_ptr<AudioEncoder> audio_encoder); |
31 ~Core(); | 101 ~Core(); |
32 | 102 |
33 void Start(); | 103 void Start(); |
34 void Pause(bool pause); | 104 void Pause(bool pause); |
35 | 105 |
36 void OnPacketSent(int size); | 106 void OnPacketSent(int size); |
37 | 107 |
38 private: | 108 private: |
| 109 std::unique_ptr<AudioPacket> Downmix(std::unique_ptr<AudioPacket> packet); |
| 110 |
39 void EncodeAudioPacket(std::unique_ptr<AudioPacket> packet); | 111 void EncodeAudioPacket(std::unique_ptr<AudioPacket> packet); |
40 | 112 |
41 base::ThreadChecker thread_checker_; | 113 base::ThreadChecker thread_checker_; |
42 | 114 |
43 base::WeakPtr<AudioPump> pump_; | 115 base::WeakPtr<AudioPump> pump_; |
44 | 116 |
45 scoped_refptr<base::SingleThreadTaskRunner> pump_task_runner_; | 117 scoped_refptr<base::SingleThreadTaskRunner> pump_task_runner_; |
46 | 118 |
47 std::unique_ptr<AudioSource> audio_source_; | 119 std::unique_ptr<AudioSource> audio_source_; |
48 std::unique_ptr<AudioEncoder> audio_encoder_; | 120 std::unique_ptr<AudioEncoder> audio_encoder_; |
49 | 121 |
50 bool enabled_; | 122 bool enabled_; |
51 | 123 |
52 // Number of bytes in the queue that have been encoded but haven't been sent | 124 // Number of bytes in the queue that have been encoded but haven't been sent |
53 // yet. | 125 // yet. |
54 int bytes_pending_; | 126 int bytes_pending_; |
55 | 127 |
| 128 std::unique_ptr<media::ChannelMixer> mixer_; |
| 129 media::ChannelLayout mixer_input_layout_ = media::CHANNEL_LAYOUT_NONE; |
| 130 |
56 DISALLOW_COPY_AND_ASSIGN(Core); | 131 DISALLOW_COPY_AND_ASSIGN(Core); |
57 }; | 132 }; |
58 | 133 |
59 AudioPump::Core::Core(base::WeakPtr<AudioPump> pump, | 134 AudioPump::Core::Core(base::WeakPtr<AudioPump> pump, |
60 std::unique_ptr<AudioSource> audio_source, | 135 std::unique_ptr<AudioSource> audio_source, |
61 std::unique_ptr<AudioEncoder> audio_encoder) | 136 std::unique_ptr<AudioEncoder> audio_encoder) |
62 : pump_(pump), | 137 : pump_(pump), |
63 pump_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 138 pump_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
64 audio_source_(std::move(audio_source)), | 139 audio_source_(std::move(audio_source)), |
65 audio_encoder_(std::move(audio_encoder)), | 140 audio_encoder_(std::move(audio_encoder)), |
(...skipping 25 matching lines...) Expand all Loading... |
91 bytes_pending_ -= size; | 166 bytes_pending_ -= size; |
92 DCHECK_GE(bytes_pending_, 0); | 167 DCHECK_GE(bytes_pending_, 0); |
93 } | 168 } |
94 | 169 |
95 void AudioPump::Core::EncodeAudioPacket(std::unique_ptr<AudioPacket> packet) { | 170 void AudioPump::Core::EncodeAudioPacket(std::unique_ptr<AudioPacket> packet) { |
96 DCHECK(thread_checker_.CalledOnValidThread()); | 171 DCHECK(thread_checker_.CalledOnValidThread()); |
97 DCHECK(packet); | 172 DCHECK(packet); |
98 | 173 |
99 int max_buffered_bytes = | 174 int max_buffered_bytes = |
100 audio_encoder_->GetBitrate() * kMaxBufferedIntervalMs / 1000 / 8; | 175 audio_encoder_->GetBitrate() * kMaxBufferedIntervalMs / 1000 / 8; |
101 if (!enabled_ || bytes_pending_ > max_buffered_bytes) | 176 if (!enabled_ || bytes_pending_ > max_buffered_bytes) { |
102 return; | 177 return; |
| 178 } |
| 179 |
| 180 if (packet->channels() > AudioPacket::CHANNELS_STEREO) { |
| 181 packet = Downmix(std::move(packet)); |
| 182 } |
103 | 183 |
104 std::unique_ptr<AudioPacket> encoded_packet = | 184 std::unique_ptr<AudioPacket> encoded_packet = |
105 audio_encoder_->Encode(std::move(packet)); | 185 audio_encoder_->Encode(std::move(packet)); |
106 | 186 |
107 // The audio encoder returns a null audio packet if there's no audio to send. | 187 // The audio encoder returns a null audio packet if there's no audio to send. |
108 if (!encoded_packet) | 188 if (!encoded_packet) |
109 return; | 189 return; |
110 | 190 |
111 int packet_size = encoded_packet->ByteSize(); | 191 int packet_size = encoded_packet->ByteSize(); |
112 bytes_pending_ += packet_size; | 192 bytes_pending_ += packet_size; |
113 | 193 |
114 pump_task_runner_->PostTask( | 194 pump_task_runner_->PostTask( |
115 FROM_HERE, base::Bind(&AudioPump::SendAudioPacket, pump_, | 195 FROM_HERE, base::Bind(&AudioPump::SendAudioPacket, pump_, |
116 base::Passed(&encoded_packet), packet_size)); | 196 base::Passed(&encoded_packet), packet_size)); |
117 } | 197 } |
118 | 198 |
| 199 std::unique_ptr<AudioPacket> AudioPump::Core::Downmix( |
| 200 std::unique_ptr<AudioPacket> packet) { |
| 201 DCHECK(thread_checker_.CalledOnValidThread()); |
| 202 DCHECK(packet); |
| 203 DCHECK_EQ(packet->data_size(), 1); |
| 204 DCHECK_EQ(packet->bytes_per_sample(), AudioPacket::BYTES_PER_SAMPLE_2); |
| 205 |
| 206 const media::ChannelLayout input_layout = RetrieveLayout(*packet); |
| 207 if (input_layout == media::CHANNEL_LAYOUT_UNSUPPORTED) { |
| 208 return nullptr; |
| 209 } |
| 210 if (input_layout == media::CHANNEL_LAYOUT_MONO || |
| 211 input_layout == media::CHANNEL_LAYOUT_STEREO) { |
| 212 return packet; |
| 213 } |
| 214 |
| 215 if (!mixer_ || mixer_input_layout_ != input_layout) { |
| 216 mixer_input_layout_ = input_layout; |
| 217 mixer_ = base::MakeUnique<media::ChannelMixer>( |
| 218 input_layout, media::CHANNEL_LAYOUT_STEREO); |
| 219 } |
| 220 |
| 221 std::unique_ptr<media::AudioBus> input = AudioPacketToAudioBus(*packet); |
| 222 if (!input) { |
| 223 return nullptr; |
| 224 } |
| 225 std::unique_ptr<media::AudioBus> output = |
| 226 media::AudioBus::Create(AudioPacket::CHANNELS_STEREO, input->frames()); |
| 227 mixer_->Transform(input.get(), output.get()); |
| 228 |
| 229 std::unique_ptr<AudioPacket> result = AudioBusToAudioPacket(*output); |
| 230 result->set_sampling_rate(packet->sampling_rate()); |
| 231 return result; |
| 232 } |
| 233 |
119 AudioPump::AudioPump( | 234 AudioPump::AudioPump( |
120 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner, | 235 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner, |
121 std::unique_ptr<AudioSource> audio_source, | 236 std::unique_ptr<AudioSource> audio_source, |
122 std::unique_ptr<AudioEncoder> audio_encoder, | 237 std::unique_ptr<AudioEncoder> audio_encoder, |
123 AudioStub* audio_stub) | 238 AudioStub* audio_stub) |
124 : audio_task_runner_(audio_task_runner), | 239 : audio_task_runner_(audio_task_runner), |
125 audio_stub_(audio_stub), | 240 audio_stub_(audio_stub), |
126 weak_factory_(this) { | 241 weak_factory_(this) { |
127 DCHECK(audio_stub_); | 242 DCHECK(audio_stub_); |
128 | 243 |
(...skipping 28 matching lines...) Expand all Loading... |
157 } | 272 } |
158 | 273 |
159 void AudioPump::OnPacketSent(int size) { | 274 void AudioPump::OnPacketSent(int size) { |
160 audio_task_runner_->PostTask( | 275 audio_task_runner_->PostTask( |
161 FROM_HERE, | 276 FROM_HERE, |
162 base::Bind(&Core::OnPacketSent, base::Unretained(core_.get()), size)); | 277 base::Bind(&Core::OnPacketSent, base::Unretained(core_.get()), size)); |
163 } | 278 } |
164 | 279 |
165 } // namespace protocol | 280 } // namespace protocol |
166 } // namespace remoting | 281 } // namespace remoting |
OLD | NEW |