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

Unified Diff: remoting/protocol/audio_pump.cc

Issue 2903153004: [Chromoting] Implement down mixing in AudioPump (Closed)
Patch Set: Resovle 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
« no previous file with comments | « remoting/protocol/audio_pump.h ('k') | remoting/protocol/audio_pump_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/protocol/audio_pump.cc
diff --git a/remoting/protocol/audio_pump.cc b/remoting/protocol/audio_pump.cc
index 66eff6ebff4d58946b7746163d2b9a1c32c2ef20..f2b00a34998dc590dbf18168d834a68f0e435c48 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();
+}
+
+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,8 +170,13 @@ 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) {
Sergey Ulanov 2017/06/07 06:24:59 Do we need this check given that Downmix() already
Hzj_jie 2017/06/07 20:27:18 Done. I have removed the if-condition in Downmix()
+ packet = Downmix(std::move(packet));
Sergey Ulanov 2017/06/07 06:24:59 Downmix() currently may return nullptr, but this c
Hzj_jie 2017/06/07 20:27:18 Done.
+ }
std::unique_ptr<AudioPacket> encoded_packet =
audio_encoder_->Encode(std::move(packet));
@@ -116,6 +193,41 @@ 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);
+ if (input_layout == media::CHANNEL_LAYOUT_UNSUPPORTED) {
+ return nullptr;
+ }
+ if (input_layout == media::CHANNEL_LAYOUT_MONO ||
+ input_layout == media::CHANNEL_LAYOUT_STEREO) {
+ return packet;
+ }
+
+ 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);
+ if (!input) {
+ return nullptr;
+ }
+ 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,
« no previous file with comments | « remoting/protocol/audio_pump.h ('k') | remoting/protocol/audio_pump_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698