diff --git a/webrtc/modules/audio_coding/BUILD.gn b/webrtc/modules/audio_coding/BUILD.gn index 544bfa0490..d1f70cf105 100644 --- a/webrtc/modules/audio_coding/BUILD.gn +++ b/webrtc/modules/audio_coding/BUILD.gn @@ -855,9 +855,11 @@ source_set("neteq") { deps = [ ":audio_decoder_interface", + ":builtin_audio_decoder_factory", ":cng", ":g711", ":pcm16b", + ":rent_a_codec", "../..:webrtc_common", "../../common_audio", "../../system_wrappers", diff --git a/webrtc/modules/audio_coding/acm2/rent_a_codec.cc b/webrtc/modules/audio_coding/acm2/rent_a_codec.cc index 7f1e52030d..a61f15949d 100644 --- a/webrtc/modules/audio_coding/acm2/rent_a_codec.cc +++ b/webrtc/modules/audio_coding/acm2/rent_a_codec.cc @@ -47,6 +47,59 @@ namespace webrtc { namespace acm2 { +rtc::Optional RentACodec::NetEqDecoderToSdpAudioFormat( + NetEqDecoder nd) { + switch (nd) { + case NetEqDecoder::kDecoderPCMu: + return rtc::Optional(SdpAudioFormat("pcmu", 8000, 1)); + case NetEqDecoder::kDecoderPCMa: + return rtc::Optional(SdpAudioFormat("pcma", 8000, 1)); + case NetEqDecoder::kDecoderPCMu_2ch: + return rtc::Optional(SdpAudioFormat("pcmu", 8000, 2)); + case NetEqDecoder::kDecoderPCMa_2ch: + return rtc::Optional(SdpAudioFormat("pcma", 8000, 2)); + case NetEqDecoder::kDecoderILBC: + return rtc::Optional(SdpAudioFormat("ilbc", 8000, 1)); + case NetEqDecoder::kDecoderISAC: + return rtc::Optional(SdpAudioFormat("isac", 16000, 1)); + case NetEqDecoder::kDecoderISACswb: + return rtc::Optional(SdpAudioFormat("isac", 32000, 1)); + case NetEqDecoder::kDecoderPCM16B: + return rtc::Optional(SdpAudioFormat("l16", 8000, 1)); + case NetEqDecoder::kDecoderPCM16Bwb: + return rtc::Optional(SdpAudioFormat("l16", 16000, 1)); + case NetEqDecoder::kDecoderPCM16Bswb32kHz: + return rtc::Optional(SdpAudioFormat("l16", 32000, 1)); + case NetEqDecoder::kDecoderPCM16Bswb48kHz: + return rtc::Optional(SdpAudioFormat("l16", 48000, 1)); + case NetEqDecoder::kDecoderPCM16B_2ch: + return rtc::Optional(SdpAudioFormat("l16", 8000, 2)); + case NetEqDecoder::kDecoderPCM16Bwb_2ch: + return rtc::Optional(SdpAudioFormat("l16", 16000, 2)); + case NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch: + return rtc::Optional(SdpAudioFormat("l16", 32000, 2)); + case NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch: + return rtc::Optional(SdpAudioFormat("l16", 48000, 2)); + case NetEqDecoder::kDecoderPCM16B_5ch: + return rtc::Optional(SdpAudioFormat("l16", 8000, 5)); + case NetEqDecoder::kDecoderG722: + return rtc::Optional(SdpAudioFormat("g722", 8000, 1)); + case NetEqDecoder::kDecoderG722_2ch: + return rtc::Optional(SdpAudioFormat("g722", 8000, 2)); + case NetEqDecoder::kDecoderOpus: + return rtc::Optional( + SdpAudioFormat("opus", 48000, 2, + std::map{{"stereo", "0"}})); + case NetEqDecoder::kDecoderOpus_2ch: + return rtc::Optional( + SdpAudioFormat("opus", 48000, 2, + std::map{{"stereo", "1"}})); + + default: + return rtc::Optional(); + } +} + rtc::Optional RentACodec::CodecIdByParams( const char* payload_name, int sampling_freq_hz, diff --git a/webrtc/modules/audio_coding/acm2/rent_a_codec.h b/webrtc/modules/audio_coding/acm2/rent_a_codec.h index a4026acd28..bac37afa96 100644 --- a/webrtc/modules/audio_coding/acm2/rent_a_codec.h +++ b/webrtc/modules/audio_coding/acm2/rent_a_codec.h @@ -20,6 +20,7 @@ #include "webrtc/base/optional.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" +#include "webrtc/modules/audio_coding/codecs/audio_format.h" #include "webrtc/modules/audio_coding/codecs/audio_encoder.h" #include "webrtc/modules/audio_coding/include/audio_coding_module_typedefs.h" #include "webrtc/typedefs.h" @@ -135,6 +136,9 @@ class RentACodec { kDecoderOpus_2ch, }; + static rtc::Optional NetEqDecoderToSdpAudioFormat( + NetEqDecoder nd); + static inline size_t NumberOfCodecs() { return static_cast(CodecId::kNumCodecs); } diff --git a/webrtc/modules/audio_coding/codecs/audio_decoder_factory_unittest.cc b/webrtc/modules/audio_coding/codecs/audio_decoder_factory_unittest.cc index d278b8473e..12a0a4047e 100644 --- a/webrtc/modules/audio_coding/codecs/audio_decoder_factory_unittest.cc +++ b/webrtc/modules/audio_coding/codecs/audio_decoder_factory_unittest.cc @@ -106,14 +106,22 @@ TEST(AudioDecoderFactoryTest, CreateG722) { TEST(AudioDecoderFactoryTest, CreateOpus) { std::unique_ptr adf = CreateBuiltinAudioDecoderFactory(); ASSERT_TRUE(adf); - // Opus supports 48 kHz, 1-2 channels. - EXPECT_FALSE(adf->MakeAudioDecoder(SdpAudioFormat("opus", 48000, 0))); - EXPECT_TRUE(adf->MakeAudioDecoder(SdpAudioFormat("opus", 48000, 1))); - EXPECT_TRUE(adf->MakeAudioDecoder(SdpAudioFormat("opus", 48000, 2))); - EXPECT_FALSE(adf->MakeAudioDecoder(SdpAudioFormat("opus", 48000, 3))); - EXPECT_FALSE(adf->MakeAudioDecoder(SdpAudioFormat("opus", 8000, 1))); - EXPECT_FALSE(adf->MakeAudioDecoder(SdpAudioFormat("opus", 16000, 1))); - EXPECT_FALSE(adf->MakeAudioDecoder(SdpAudioFormat("opus", 32000, 1))); + // Opus supports 48 kHz, 2 channels, and wants a "stereo" parameter whose + // value is either "0" or "1". + for (int hz : {8000, 16000, 32000, 48000}) { + for (int channels : {0, 1, 2, 3}) { + for (std::string stereo : {"XX", "0", "1", "2"}) { + std::map params; + if (stereo != "XX") { + params["stereo"] = stereo; + } + bool good = + (hz == 48000 && channels == 2 && (stereo == "0" || stereo == "1")); + EXPECT_EQ(good, static_cast(adf->MakeAudioDecoder(SdpAudioFormat( + "opus", hz, channels, std::move(params))))); + } + } + } } } // namespace webrtc diff --git a/webrtc/modules/audio_coding/codecs/audio_format.cc b/webrtc/modules/audio_coding/codecs/audio_format.cc index b2acf09de6..bb69cbdb2f 100644 --- a/webrtc/modules/audio_coding/codecs/audio_format.cc +++ b/webrtc/modules/audio_coding/codecs/audio_format.cc @@ -21,6 +21,15 @@ SdpAudioFormat::SdpAudioFormat(const char* name, int num_channels) : name(name), clockrate_hz(clockrate_hz), num_channels(num_channels) {} +SdpAudioFormat::SdpAudioFormat(const char* name, + int clockrate_hz, + int num_channels, + Parameters&& param) + : name(name), + clockrate_hz(clockrate_hz), + num_channels(num_channels), + parameters(std::move(param)) {} + SdpAudioFormat::~SdpAudioFormat() = default; SdpAudioFormat& SdpAudioFormat::operator=(const SdpAudioFormat&) = default; SdpAudioFormat& SdpAudioFormat::operator=(SdpAudioFormat&&) = default; diff --git a/webrtc/modules/audio_coding/codecs/audio_format.h b/webrtc/modules/audio_coding/codecs/audio_format.h index 7ad7edd429..61c0dd9f6f 100644 --- a/webrtc/modules/audio_coding/codecs/audio_format.h +++ b/webrtc/modules/audio_coding/codecs/audio_format.h @@ -21,18 +21,23 @@ namespace webrtc { // SDP specification for a single audio codec. // NOTE: This class is still under development and may change without notice. struct SdpAudioFormat { + using Parameters = std::map; + // TODO(kwiberg): Get rid of the default constructor when rtc::Optional no // longer requires it. SdpAudioFormat(); SdpAudioFormat(const SdpAudioFormat&); SdpAudioFormat(SdpAudioFormat&&); SdpAudioFormat(const char* name, int clockrate_hz, int num_channels); + SdpAudioFormat(const char* name, + int clockrate_hz, + int num_channels, + Parameters&& param); ~SdpAudioFormat(); SdpAudioFormat& operator=(const SdpAudioFormat&); SdpAudioFormat& operator=(SdpAudioFormat&&); - using Parameters = std::map; std::string name; int clockrate_hz; int num_channels; diff --git a/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.cc b/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.cc index 12a6afe2cc..4c7445672a 100644 --- a/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.cc +++ b/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.cc @@ -13,6 +13,7 @@ #include #include "webrtc/base/checks.h" +#include "webrtc/base/optional.h" #include "webrtc/common_types.h" #include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h" #include "webrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h" @@ -39,8 +40,7 @@ namespace { struct NamedDecoderConstructor { const char* name; - std::unique_ptr (*constructor)(int clockrate_hz, - int num_channels); + std::unique_ptr (*constructor)(const SdpAudioFormat&); }; std::unique_ptr Unique(AudioDecoder* d) { @@ -51,53 +51,54 @@ std::unique_ptr Unique(AudioDecoder* d) { // decoder. NamedDecoderConstructor decoder_constructors[] = { {"pcmu", - [](int clockrate_hz, int num_channels) { - return clockrate_hz == 8000 && num_channels >= 1 - ? Unique(new AudioDecoderPcmU(num_channels)) + [](const SdpAudioFormat& format) { + return format.clockrate_hz == 8000 && format.num_channels >= 1 + ? Unique(new AudioDecoderPcmU(format.num_channels)) : nullptr; }}, {"pcma", - [](int clockrate_hz, int num_channels) { - return clockrate_hz == 8000 && num_channels >= 1 - ? Unique(new AudioDecoderPcmA(num_channels)) + [](const SdpAudioFormat& format) { + return format.clockrate_hz == 8000 && format.num_channels >= 1 + ? Unique(new AudioDecoderPcmA(format.num_channels)) : nullptr; }}, #ifdef WEBRTC_CODEC_ILBC {"ilbc", - [](int clockrate_hz, int num_channels) { - return clockrate_hz == 8000 && num_channels == 1 + [](const SdpAudioFormat& format) { + return format.clockrate_hz == 8000 && format.num_channels == 1 ? Unique(new AudioDecoderIlbc) : nullptr; }}, #endif #if defined(WEBRTC_CODEC_ISACFX) {"isac", - [](int clockrate_hz, int num_channels) { - return clockrate_hz == 16000 && num_channels == 1 + [](const SdpAudioFormat& format) { + return format.clockrate_hz == 16000 && format.num_channels == 1 ? Unique(new AudioDecoderIsacFix) : nullptr; }}, #elif defined(WEBRTC_CODEC_ISAC) {"isac", - [](int clockrate_hz, int num_channels) { - return (clockrate_hz == 16000 || clockrate_hz == 32000) && - num_channels == 1 + [](const SdpAudioFormat& format) { + return (format.clockrate_hz == 16000 || format.clockrate_hz == 32000) && + format.num_channels == 1 ? Unique(new AudioDecoderIsac) : nullptr; }}, #endif {"l16", - [](int clockrate_hz, int num_channels) { - return num_channels >= 1 ? Unique(new AudioDecoderPcm16B(num_channels)) - : nullptr; + [](const SdpAudioFormat& format) { + return format.num_channels >= 1 + ? Unique(new AudioDecoderPcm16B(format.num_channels)) + : nullptr; }}, #ifdef WEBRTC_CODEC_G722 {"g722", - [](int clockrate_hz, int num_channels) { - if (clockrate_hz == 8000) { - if (num_channels == 1) + [](const SdpAudioFormat& format) { + if (format.clockrate_hz == 8000) { + if (format.num_channels == 1) return Unique(new AudioDecoderG722); - if (num_channels == 2) + if (format.num_channels == 2) return Unique(new AudioDecoderG722Stereo); } return Unique(nullptr); @@ -105,9 +106,21 @@ NamedDecoderConstructor decoder_constructors[] = { #endif #ifdef WEBRTC_CODEC_OPUS {"opus", - [](int clockrate_hz, int num_channels) { - return clockrate_hz == 48000 && (num_channels == 1 || num_channels == 2) - ? Unique(new AudioDecoderOpus(num_channels)) + [](const SdpAudioFormat& format) { + rtc::Optional num_channels = [&] { + auto stereo = format.parameters.find("stereo"); + if (stereo != format.parameters.end()) { + if (stereo->second == "0") { + return rtc::Optional(1); + } else if (stereo->second == "1") { + return rtc::Optional(2); + } + } + return rtc::Optional(); + }(); + return format.clockrate_hz == 48000 && format.num_channels == 2 && + num_channels + ? Unique(new AudioDecoderOpus(*num_channels)) : nullptr; }}, #endif @@ -123,8 +136,7 @@ class BuiltinAudioDecoderFactory : public AudioDecoderFactory { const SdpAudioFormat& format) override { for (const auto& dc : decoder_constructors) { if (STR_CASE_CMP(format.name.c_str(), dc.name) == 0) { - return std::unique_ptr( - dc.constructor(format.clockrate_hz, format.num_channels)); + return std::unique_ptr(dc.constructor(format)); } } return nullptr; diff --git a/webrtc/modules/audio_coding/codecs/mock/mock_audio_decoder_factory.h b/webrtc/modules/audio_coding/codecs/mock/mock_audio_decoder_factory.h new file mode 100644 index 0000000000..6e5737c89b --- /dev/null +++ b/webrtc/modules/audio_coding/codecs/mock/mock_audio_decoder_factory.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_MOCK_MOCK_AUDIO_DECODER_FACTORY_H_ +#define WEBRTC_MODULES_AUDIO_CODING_CODECS_MOCK_MOCK_AUDIO_DECODER_FACTORY_H_ + +#include + +#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/modules/audio_coding/codecs/audio_decoder_factory.h" + +namespace webrtc { + +class MockAudioDecoderFactory : public AudioDecoderFactory { + public: + MOCK_METHOD0(GetSupportedFormats, std::vector()); + std::unique_ptr MakeAudioDecoder( + const SdpAudioFormat& format) { + std::unique_ptr return_value; + MakeAudioDecoderMock(format, &return_value); + return return_value; + } + MOCK_METHOD2(MakeAudioDecoderMock, + void(const SdpAudioFormat& format, + std::unique_ptr* return_value)); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_MOCK_MOCK_AUDIO_DECODER_FACTORY_H_ diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc index c9b9b6ae67..762c385983 100644 --- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc +++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc @@ -137,67 +137,4 @@ int CodecSampleRateHz(NetEqDecoder codec_type) { } } -AudioDecoder* CreateAudioDecoder(NetEqDecoder codec_type) { - if (!CodecSupported(codec_type)) { - return NULL; - } - switch (codec_type) { - case NetEqDecoder::kDecoderPCMu: - return new AudioDecoderPcmU(1); - case NetEqDecoder::kDecoderPCMa: - return new AudioDecoderPcmA(1); - case NetEqDecoder::kDecoderPCMu_2ch: - return new AudioDecoderPcmU(2); - case NetEqDecoder::kDecoderPCMa_2ch: - return new AudioDecoderPcmA(2); -#ifdef WEBRTC_CODEC_ILBC - case NetEqDecoder::kDecoderILBC: - return new AudioDecoderIlbc; -#endif -#if defined(WEBRTC_CODEC_ISACFX) - case NetEqDecoder::kDecoderISAC: - return new AudioDecoderIsacFix(); -#elif defined(WEBRTC_CODEC_ISAC) - case NetEqDecoder::kDecoderISAC: - case NetEqDecoder::kDecoderISACswb: - return new AudioDecoderIsac(); -#endif - case NetEqDecoder::kDecoderPCM16B: - case NetEqDecoder::kDecoderPCM16Bwb: - case NetEqDecoder::kDecoderPCM16Bswb32kHz: - case NetEqDecoder::kDecoderPCM16Bswb48kHz: - return new AudioDecoderPcm16B(1); - case NetEqDecoder::kDecoderPCM16B_2ch: - case NetEqDecoder::kDecoderPCM16Bwb_2ch: - case NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch: - case NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch: - return new AudioDecoderPcm16B(2); - case NetEqDecoder::kDecoderPCM16B_5ch: - return new AudioDecoderPcm16B(5); -#ifdef WEBRTC_CODEC_G722 - case NetEqDecoder::kDecoderG722: - return new AudioDecoderG722; - case NetEqDecoder::kDecoderG722_2ch: - return new AudioDecoderG722Stereo; -#endif -#ifdef WEBRTC_CODEC_OPUS - case NetEqDecoder::kDecoderOpus: - return new AudioDecoderOpus(1); - case NetEqDecoder::kDecoderOpus_2ch: - return new AudioDecoderOpus(2); -#endif - case NetEqDecoder::kDecoderCNGnb: - case NetEqDecoder::kDecoderCNGwb: - case NetEqDecoder::kDecoderCNGswb32kHz: - case NetEqDecoder::kDecoderCNGswb48kHz: - RTC_CHECK(false) << "CNG should not be created like this anymore!"; - case NetEqDecoder::kDecoderRED: - case NetEqDecoder::kDecoderAVT: - case NetEqDecoder::kDecoderArbitrary: - default: { - return NULL; - } - } -} - } // namespace webrtc diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h index d9a1d814f1..579ccb36f7 100644 --- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h +++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h @@ -32,10 +32,5 @@ bool CodecSupported(NetEqDecoder codec_type); // Returns the sample rate for |codec_type|. int CodecSampleRateHz(NetEqDecoder codec_type); -// Creates an AudioDecoder object of type |codec_type|. Returns NULL for for -// unsupported codecs, and when creating an AudioDecoder is not applicable -// (e.g., for RED and DTMF/AVT types). -AudioDecoder* CreateAudioDecoder(NetEqDecoder codec_type); - } // namespace webrtc #endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_AUDIO_DECODER_IMPL_H_ diff --git a/webrtc/modules/audio_coding/neteq/decision_logic_unittest.cc b/webrtc/modules/audio_coding/neteq/decision_logic_unittest.cc index 7165d93cf7..dd71953f1a 100644 --- a/webrtc/modules/audio_coding/neteq/decision_logic_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/decision_logic_unittest.cc @@ -11,6 +11,7 @@ // Unit tests for DecisionLogic class and derived classes. #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/audio_coding/codecs/mock/mock_audio_decoder_factory.h" #include "webrtc/modules/audio_coding/neteq/buffer_level_filter.h" #include "webrtc/modules/audio_coding/neteq/decoder_database.h" #include "webrtc/modules/audio_coding/neteq/decision_logic.h" @@ -24,7 +25,8 @@ namespace webrtc { TEST(DecisionLogic, CreateAndDestroy) { int fs_hz = 8000; int output_size_samples = fs_hz / 100; // Samples per 10 ms. - DecoderDatabase decoder_database; + DecoderDatabase decoder_database( + std::unique_ptr(new MockAudioDecoderFactory)); TickTimer tick_timer; PacketBuffer packet_buffer(10, &tick_timer); DelayPeakDetector delay_peak_detector(&tick_timer); diff --git a/webrtc/modules/audio_coding/neteq/decoder_database.cc b/webrtc/modules/audio_coding/neteq/decoder_database.cc index 845b2adaef..4fddf75ce2 100644 --- a/webrtc/modules/audio_coding/neteq/decoder_database.cc +++ b/webrtc/modules/audio_coding/neteq/decoder_database.cc @@ -19,9 +19,11 @@ namespace webrtc { -DecoderDatabase::DecoderDatabase() - : active_decoder_type_(-1), active_cng_decoder_type_(-1) { -} +DecoderDatabase::DecoderDatabase( + std::unique_ptr decoder_factory) + : active_decoder_type_(-1), + active_cng_decoder_type_(-1), + decoder_factory_(std::move(decoder_factory)) {} DecoderDatabase::~DecoderDatabase() = default; @@ -32,20 +34,23 @@ DecoderDatabase::DecoderInfo::DecoderInfo(NetEqDecoder ct, : codec_type(ct), name(nm), fs_hz(fs), - external_decoder(ext_dec) {} + external_decoder(ext_dec), + audio_format_(acm2::RentACodec::NetEqDecoderToSdpAudioFormat(ct)) {} DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default; DecoderDatabase::DecoderInfo::~DecoderInfo() = default; -AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() { +AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder( + AudioDecoderFactory* factory) { if (external_decoder) { RTC_DCHECK(!decoder_); return external_decoder; } + RTC_DCHECK(audio_format_); if (!decoder_) { - decoder_.reset(CreateAudioDecoder(codec_type)); + decoder_ = factory->MakeAudioDecoder(*audio_format_); } - RTC_DCHECK(decoder_); + RTC_DCHECK(decoder_) << "Failed to create: " << *audio_format_; return decoder_.get(); } @@ -155,7 +160,7 @@ AudioDecoder* DecoderDatabase::GetDecoder(uint8_t rtp_payload_type) { return NULL; } DecoderInfo* info = &(*it).second; - return info->GetDecoder(); + return info->GetDecoder(decoder_factory_.get()); } bool DecoderDatabase::IsType(uint8_t rtp_payload_type, diff --git a/webrtc/modules/audio_coding/neteq/decoder_database.h b/webrtc/modules/audio_coding/neteq/decoder_database.h index ec8a5d69bc..3a40e08c8a 100644 --- a/webrtc/modules/audio_coding/neteq/decoder_database.h +++ b/webrtc/modules/audio_coding/neteq/decoder_database.h @@ -17,6 +17,8 @@ #include "webrtc/base/constructormagic.h" #include "webrtc/common_types.h" // NULL +#include "webrtc/modules/audio_coding/codecs/audio_decoder_factory.h" +#include "webrtc/modules/audio_coding/codecs/audio_format.h" #include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h" #include "webrtc/modules/audio_coding/neteq/audio_decoder_impl.h" #include "webrtc/modules/audio_coding/neteq/packet.h" @@ -47,7 +49,7 @@ class DecoderDatabase { ~DecoderInfo(); // Get the AudioDecoder object, creating it first if necessary. - AudioDecoder* GetDecoder(); + AudioDecoder* GetDecoder(AudioDecoderFactory* factory); // Delete the AudioDecoder object, unless it's external. (This means we can // always recreate it later if we need it.) @@ -59,6 +61,7 @@ class DecoderDatabase { AudioDecoder* const external_decoder; private: + const rtc::Optional audio_format_; std::unique_ptr decoder_; }; @@ -66,7 +69,7 @@ class DecoderDatabase { // only 7 bits). static const uint8_t kRtpPayloadTypeError = 0xFF; - DecoderDatabase(); + DecoderDatabase(std::unique_ptr decoder_factory); virtual ~DecoderDatabase(); @@ -157,6 +160,7 @@ class DecoderDatabase { int active_decoder_type_; int active_cng_decoder_type_; std::unique_ptr active_cng_decoder_; + const std::unique_ptr decoder_factory_; RTC_DISALLOW_COPY_AND_ASSIGN(DecoderDatabase); }; diff --git a/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc b/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc index 0da4d640f3..91ca606d65 100644 --- a/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc @@ -19,17 +19,21 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h" +#include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h" +#include "webrtc/modules/audio_coding/codecs/mock/mock_audio_decoder_factory.h" namespace webrtc { TEST(DecoderDatabase, CreateAndDestroy) { - DecoderDatabase db; + std::unique_ptr factory(new MockAudioDecoderFactory); + DecoderDatabase db(std::move(factory)); EXPECT_EQ(0, db.Size()); EXPECT_TRUE(db.Empty()); } TEST(DecoderDatabase, InsertAndRemove) { - DecoderDatabase db; + std::unique_ptr factory(new MockAudioDecoderFactory); + DecoderDatabase db(std::move(factory)); const uint8_t kPayloadType = 0; const std::string kCodecName = "Robert\'); DROP TABLE Students;"; EXPECT_EQ( @@ -43,7 +47,8 @@ TEST(DecoderDatabase, InsertAndRemove) { } TEST(DecoderDatabase, GetDecoderInfo) { - DecoderDatabase db; + std::unique_ptr factory(new MockAudioDecoderFactory); + DecoderDatabase db(std::move(factory)); const uint8_t kPayloadType = 0; const std::string kCodecName = "Robert\'); DROP TABLE Students;"; EXPECT_EQ( @@ -61,7 +66,8 @@ TEST(DecoderDatabase, GetDecoderInfo) { } TEST(DecoderDatabase, GetRtpPayloadType) { - DecoderDatabase db; + std::unique_ptr factory(new MockAudioDecoderFactory); + DecoderDatabase db(std::move(factory)); const uint8_t kPayloadType = 0; const std::string kCodecName = "Robert\'); DROP TABLE Students;"; EXPECT_EQ( @@ -75,7 +81,7 @@ TEST(DecoderDatabase, GetRtpPayloadType) { } TEST(DecoderDatabase, GetDecoder) { - DecoderDatabase db; + DecoderDatabase db(CreateBuiltinAudioDecoderFactory()); const uint8_t kPayloadType = 0; const std::string kCodecName = "Robert\'); DROP TABLE Students;"; EXPECT_EQ(DecoderDatabase::kOK, @@ -86,7 +92,8 @@ TEST(DecoderDatabase, GetDecoder) { } TEST(DecoderDatabase, TypeTests) { - DecoderDatabase db; + std::unique_ptr factory(new MockAudioDecoderFactory); + DecoderDatabase db(std::move(factory)); const uint8_t kPayloadTypePcmU = 0; const uint8_t kPayloadTypeCng = 13; const uint8_t kPayloadTypeDtmf = 100; @@ -121,7 +128,8 @@ TEST(DecoderDatabase, TypeTests) { } TEST(DecoderDatabase, ExternalDecoder) { - DecoderDatabase db; + std::unique_ptr factory(new MockAudioDecoderFactory); + DecoderDatabase db(std::move(factory)); const uint8_t kPayloadType = 0; const std::string kCodecName = "Robert\'); DROP TABLE Students;"; MockAudioDecoder decoder; @@ -150,7 +158,8 @@ TEST(DecoderDatabase, ExternalDecoder) { } TEST(DecoderDatabase, CheckPayloadTypes) { - DecoderDatabase db; + std::unique_ptr factory(new MockAudioDecoderFactory); + DecoderDatabase db(std::move(factory)); // Load a number of payloads into the database. Payload types are 0, 1, ..., // while the decoder type is the same for all payload types (this does not // matter for the test). @@ -194,7 +203,7 @@ TEST(DecoderDatabase, CheckPayloadTypes) { // Test the methods for setting and getting active speech and CNG decoders. TEST(DecoderDatabase, IF_ISAC(ActiveDecoders)) { - DecoderDatabase db; + DecoderDatabase db(CreateBuiltinAudioDecoderFactory()); // Load payload types. ASSERT_EQ(DecoderDatabase::kOK, db.RegisterPayload(0, NetEqDecoder::kDecoderPCMu, "pcmu")); diff --git a/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h b/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h index d04181d55b..60ae0f6501 100644 --- a/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h +++ b/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h @@ -21,6 +21,7 @@ namespace webrtc { class MockDecoderDatabase : public DecoderDatabase { public: + MockDecoderDatabase() : DecoderDatabase(nullptr) {} virtual ~MockDecoderDatabase() { Die(); } MOCK_METHOD0(Die, void()); MOCK_CONST_METHOD0(Empty, diff --git a/webrtc/modules/audio_coding/neteq/neteq.gypi b/webrtc/modules/audio_coding/neteq/neteq.gypi index 509dda0c6e..e92567eef5 100644 --- a/webrtc/modules/audio_coding/neteq/neteq.gypi +++ b/webrtc/modules/audio_coding/neteq/neteq.gypi @@ -51,6 +51,8 @@ 'dependencies': [ '<@(neteq_dependencies)', '<(webrtc_root)/common.gyp:webrtc_common', + 'builtin_audio_decoder_factory', + 'rent_a_codec', ], 'defines': [ '<@(neteq_defines)', diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc index 2eb22772ee..b4ba650fef 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc @@ -22,6 +22,7 @@ #include "webrtc/base/trace_event.h" #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" +#include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h" #include "webrtc/modules/audio_coding/neteq/accelerate.h" #include "webrtc/modules/audio_coding/neteq/background_noise.h" #include "webrtc/modules/audio_coding/neteq/buffer_level_filter.h" @@ -57,7 +58,7 @@ namespace webrtc { NetEqImpl::Dependencies::Dependencies(const NetEq::Config& config) : tick_timer(new TickTimer), buffer_level_filter(new BufferLevelFilter), - decoder_database(new DecoderDatabase), + decoder_database(new DecoderDatabase(CreateBuiltinAudioDecoderFactory())), delay_peak_detector(new DelayPeakDetector(tick_timer.get())), delay_manager(new DelayManager(config.max_packets_in_buffer, delay_peak_detector.get(), diff --git a/webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc b/webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc index 98d9961861..63772452da 100644 --- a/webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc @@ -18,6 +18,8 @@ #include // pair #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h" +#include "webrtc/modules/audio_coding/codecs/mock/mock_audio_decoder_factory.h" #include "webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h" #include "webrtc/modules/audio_coding/neteq/packet.h" @@ -309,7 +311,8 @@ TEST(RedPayloadSplitter, CheckRedPayloads) { // Use a real DecoderDatabase object here instead of a mock, since it is // easier to just register the payload types and let the actual implementation // do its job. - DecoderDatabase decoder_database; + std::unique_ptr factory(new MockAudioDecoderFactory); + DecoderDatabase decoder_database(std::move(factory)); decoder_database.RegisterPayload(0, NetEqDecoder::kDecoderCNGnb, "cng-nb"); decoder_database.RegisterPayload(1, NetEqDecoder::kDecoderPCMu, "pcmu"); decoder_database.RegisterPayload(2, NetEqDecoder::kDecoderAVT, "avt"); @@ -743,7 +746,7 @@ TEST(IlbcPayloadSplitter, UnevenPayload) { TEST(FecPayloadSplitter, MixedPayload) { PacketList packet_list; - DecoderDatabase decoder_database; + DecoderDatabase decoder_database(CreateBuiltinAudioDecoderFactory()); decoder_database.RegisterPayload(0, NetEqDecoder::kDecoderOpus, "opus"); decoder_database.RegisterPayload(1, NetEqDecoder::kDecoderPCMu, "pcmu"); @@ -798,7 +801,7 @@ TEST(FecPayloadSplitter, MixedPayload) { TEST(FecPayloadSplitter, EmbedFecInRed) { PacketList packet_list; - DecoderDatabase decoder_database; + DecoderDatabase decoder_database(CreateBuiltinAudioDecoderFactory()); const int kTimestampOffset = 20 * 48; // 20 ms * 48 kHz. uint8_t payload_types[] = {0, 0};