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

Unified Diff: remoting/protocol/audio_pump.cc

Issue 2903153004: [Chromoting] Implement down mixing in AudioPump (Closed)
Patch Set: Resolve review comments Created 3 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: remoting/protocol/audio_pump.cc
diff --git a/remoting/protocol/audio_pump.cc b/remoting/protocol/audio_pump.cc
index 66eff6ebff4d58946b7746163d2b9a1c32c2ef20..525ea24a490f3668459f83ce46d8def5fc6378fc 100644
--- a/remoting/protocol/audio_pump.cc
+++ b/remoting/protocol/audio_pump.cc
@@ -4,19 +4,86 @@
#include "remoting/protocol/audio_pump.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "media/base/audio_bus.h"
+#include "media/base/audio_sample_types.h"
+#include "media/base/channel_layout.h"
+#include "media/base/channel_mixer.h"
#include "remoting/codec/audio_encoder.h"
#include "remoting/proto/audio.pb.h"
#include "remoting/protocol/audio_source.h"
#include "remoting/protocol/audio_stub.h"
+namespace {
+
+int CalculateFrameCount(const remoting::AudioPacket& packet) {
+ return packet.data(0).size() / packet.channels() / packet.bytes_per_sample();
chcunningham 2017/06/08 16:39:45 I think this calculation could go sideways if you
Hzj_jie 2017/06/08 19:07:48 We do not change the dwChannelMask returned by Get
+}
+
+std::unique_ptr<media::AudioBus> AudioPacketToAudioBus(
+ const remoting::AudioPacket& packet) {
+ const int frame_count = CalculateFrameCount(packet);
+ DCHECK_GT(frame_count, 0);
+ std::unique_ptr<media::AudioBus> result =
+ media::AudioBus::Create(packet.channels(), frame_count);
+ result->FromInterleaved<media::SignedInt16SampleTypeTraits>(
+ reinterpret_cast<const int16_t*>(packet.data(0).data()), frame_count);
+ return result;
+}
+
+std::unique_ptr<remoting::AudioPacket> AudioBusToAudioPacket(
+ const media::AudioBus& packet) {
+ std::unique_ptr<remoting::AudioPacket> result =
+ base::MakeUnique<remoting::AudioPacket>();
+ result->add_data()->resize(
+ packet.channels() * packet.frames() * sizeof(int16_t));
+ packet.ToInterleaved<media::SignedInt16SampleTypeTraits>(
+ packet.frames(),
+ reinterpret_cast<int16_t*>(&(result->mutable_data(0)->at(0))));
+ result->set_encoding(remoting::AudioPacket::ENCODING_RAW);
+ result->set_channels(
+ static_cast<remoting::AudioPacket::Channels>(packet.channels()));
+ result->set_bytes_per_sample(remoting::AudioPacket::BYTES_PER_SAMPLE_2);
+ return result;
+}
+
+media::ChannelLayout RetrieveLayout(const remoting::AudioPacket& packet) {
+ // This switch should match AudioPacket::Channels enum in audio.proto.
+ switch (packet.channels()) {
+ case remoting::AudioPacket::CHANNELS_INVALID:
+ return media::CHANNEL_LAYOUT_UNSUPPORTED;
+ case remoting::AudioPacket::CHANNELS_MONO:
+ return media::CHANNEL_LAYOUT_MONO;
+ case remoting::AudioPacket::CHANNELS_STEREO:
+ return media::CHANNEL_LAYOUT_STEREO;
+ case remoting::AudioPacket::CHANNELS_SURROUND:
+ return media::CHANNEL_LAYOUT_SURROUND;
+ case remoting::AudioPacket::CHANNELS_4_0:
+ return media::CHANNEL_LAYOUT_4_0;
+ case remoting::AudioPacket::CHANNELS_4_1:
+ return media::CHANNEL_LAYOUT_4_1;
+ case remoting::AudioPacket::CHANNELS_5_1:
+ return media::CHANNEL_LAYOUT_5_1;
+ case remoting::AudioPacket::CHANNELS_6_1:
+ return media::CHANNEL_LAYOUT_6_1;
+ case remoting::AudioPacket::CHANNELS_7_1:
+ return media::CHANNEL_LAYOUT_7_1;
+ }
+ NOTREACHED() << "Invalid AudioPacket::Channels";
+ return media::CHANNEL_LAYOUT_UNSUPPORTED;
+}
+
+} // namespace
+
namespace remoting {
namespace protocol {
@@ -36,6 +103,8 @@ class AudioPump::Core {
void OnPacketSent(int size);
private:
+ std::unique_ptr<AudioPacket> Downmix(std::unique_ptr<AudioPacket> packet);
+
void EncodeAudioPacket(std::unique_ptr<AudioPacket> packet);
base::ThreadChecker thread_checker_;
@@ -53,6 +122,9 @@ class AudioPump::Core {
// yet.
int bytes_pending_;
+ std::unique_ptr<media::ChannelMixer> mixer_;
+ media::ChannelLayout mixer_input_layout_ = media::CHANNEL_LAYOUT_NONE;
+
DISALLOW_COPY_AND_ASSIGN(Core);
};
@@ -98,15 +170,21 @@ void AudioPump::Core::EncodeAudioPacket(std::unique_ptr<AudioPacket> packet) {
int max_buffered_bytes =
audio_encoder_->GetBitrate() * kMaxBufferedIntervalMs / 1000 / 8;
- if (!enabled_ || bytes_pending_ > max_buffered_bytes)
+ if (!enabled_ || bytes_pending_ > max_buffered_bytes) {
return;
+ }
+
+ if (packet->channels() > AudioPacket::CHANNELS_STEREO) {
+ packet = Downmix(std::move(packet));
+ }
std::unique_ptr<AudioPacket> encoded_packet =
audio_encoder_->Encode(std::move(packet));
// The audio encoder returns a null audio packet if there's no audio to send.
- if (!encoded_packet)
+ if (!encoded_packet) {
return;
+ }
int packet_size = encoded_packet->ByteSize();
bytes_pending_ += packet_size;
@@ -116,6 +194,35 @@ void AudioPump::Core::EncodeAudioPacket(std::unique_ptr<AudioPacket> packet) {
base::Passed(&encoded_packet), packet_size));
}
+std::unique_ptr<AudioPacket> AudioPump::Core::Downmix(
+ std::unique_ptr<AudioPacket> packet) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(packet);
+ DCHECK_EQ(packet->data_size(), 1);
+ DCHECK_EQ(packet->bytes_per_sample(), AudioPacket::BYTES_PER_SAMPLE_2);
+
+ const media::ChannelLayout input_layout = RetrieveLayout(*packet);
+ DCHECK_NE(input_layout, media::CHANNEL_LAYOUT_UNSUPPORTED);
+ DCHECK_NE(input_layout, media::CHANNEL_LAYOUT_MONO);
+ DCHECK_NE(input_layout, media::CHANNEL_LAYOUT_STEREO);
+
+ if (!mixer_ || mixer_input_layout_ != input_layout) {
+ mixer_input_layout_ = input_layout;
+ mixer_ = base::MakeUnique<media::ChannelMixer>(
+ input_layout, media::CHANNEL_LAYOUT_STEREO);
+ }
+
+ std::unique_ptr<media::AudioBus> input = AudioPacketToAudioBus(*packet);
+ DCHECK(input);
+ std::unique_ptr<media::AudioBus> output =
+ media::AudioBus::Create(AudioPacket::CHANNELS_STEREO, input->frames());
+ mixer_->Transform(input.get(), output.get());
+
+ std::unique_ptr<AudioPacket> result = AudioBusToAudioPacket(*output);
+ result->set_sampling_rate(packet->sampling_rate());
+ return result;
+}
+
AudioPump::AudioPump(
scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
std::unique_ptr<AudioSource> audio_source,

Powered by Google App Engine
This is Rietveld 408576698