diff --git a/api/test/neteq_simulator_factory.cc b/api/test/neteq_simulator_factory.cc index 88ed158a45..71181146da 100644 --- a/api/test/neteq_simulator_factory.cc +++ b/api/test/neteq_simulator_factory.cc @@ -15,6 +15,18 @@ #include "rtc_base/checks.h" #include "rtc_base/flags.h" +namespace { + +WEBRTC_DEFINE_string(replacement_audio_file, + "", + "A PCM file that will be used to populate dummy" + " RTP packets"); +WEBRTC_DEFINE_int(max_nr_packets_in_buffer, + 50, + "Maximum allowed number of packets in the buffer"); + +} // namespace + namespace webrtc { namespace test { @@ -30,7 +42,11 @@ std::unique_ptr NetEqSimulatorFactory::CreateSimulator( << "Error while parsing command-line flags"; RTC_CHECK_EQ(argc, 3) << "Wrong number of input arguments. Expected 3, got " << argc; - return factory_->InitializeTest(argv[1], argv[2]); + // TODO(ivoc) Stop (ab)using command-line flags in this function. + NetEqTestFactory::Config config; + config.replacement_audio_file = FLAG_replacement_audio_file; + config.max_nr_packets_in_buffer = FLAG_max_nr_packets_in_buffer; + return factory_->InitializeTest(argv[1], argv[2], config); } } // namespace test diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn index 34cee985a5..55b5078cea 100644 --- a/modules/audio_coding/BUILD.gn +++ b/modules/audio_coding/BUILD.gn @@ -1467,6 +1467,7 @@ if (rtc_include_tests) { deps = [ "../../rtc_base:checks", "../../test:fileutils", + "//third_party/abseil-cpp/absl/types:optional", ] sources = [ "neteq/tools/neteq_test_factory.cc", diff --git a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc index c2726eb470..36c03b8eef 100644 --- a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc +++ b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc @@ -17,6 +17,10 @@ #include "system_wrappers/include/field_trial.h" #include "test/field_trial.h" +namespace { + +using TestConfig = webrtc::test::NetEqTestFactory::Config; + WEBRTC_DEFINE_bool(codec_map, false, "Prints the mapping between RTP payload type and " @@ -28,6 +32,185 @@ WEBRTC_DEFINE_string( "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/" " will assign the group Enable to field trial WebRTC-FooFeature."); WEBRTC_DEFINE_bool(help, false, "Prints this message"); +// Define command line flags. +WEBRTC_DEFINE_int(pcmu, + TestConfig::default_pcmu(), + "RTP payload type for PCM-u"); +WEBRTC_DEFINE_int(pcma, + TestConfig::default_pcma(), + "RTP payload type for PCM-a"); +WEBRTC_DEFINE_int(ilbc, + TestConfig::default_ilbc(), + "RTP payload type for iLBC"); +WEBRTC_DEFINE_int(isac, + TestConfig::default_isac(), + "RTP payload type for iSAC"); +WEBRTC_DEFINE_int(isac_swb, + TestConfig::default_isac_swb(), + "RTP payload type for iSAC-swb (32 kHz)"); +WEBRTC_DEFINE_int(opus, + TestConfig::default_opus(), + "RTP payload type for Opus"); +WEBRTC_DEFINE_int(pcm16b, + TestConfig::default_pcm16b(), + "RTP payload type for PCM16b-nb (8 kHz)"); +WEBRTC_DEFINE_int(pcm16b_wb, + TestConfig::default_pcm16b_wb(), + "RTP payload type for PCM16b-wb (16 kHz)"); +WEBRTC_DEFINE_int(pcm16b_swb32, + TestConfig::default_pcm16b_swb32(), + "RTP payload type for PCM16b-swb32 (32 kHz)"); +WEBRTC_DEFINE_int(pcm16b_swb48, + TestConfig::default_pcm16b_swb48(), + "RTP payload type for PCM16b-swb48 (48 kHz)"); +WEBRTC_DEFINE_int(g722, + TestConfig::default_g722(), + "RTP payload type for G.722"); +WEBRTC_DEFINE_int(avt, + TestConfig::default_avt(), + "RTP payload type for AVT/DTMF (8 kHz)"); +WEBRTC_DEFINE_int(avt_16, + TestConfig::default_avt_16(), + "RTP payload type for AVT/DTMF (16 kHz)"); +WEBRTC_DEFINE_int(avt_32, + TestConfig::default_avt_32(), + "RTP payload type for AVT/DTMF (32 kHz)"); +WEBRTC_DEFINE_int(avt_48, + TestConfig::default_avt_48(), + "RTP payload type for AVT/DTMF (48 kHz)"); +WEBRTC_DEFINE_int(red, + TestConfig::default_red(), + "RTP payload type for redundant audio (RED)"); +WEBRTC_DEFINE_int(cn_nb, + TestConfig::default_cn_nb(), + "RTP payload type for comfort noise (8 kHz)"); +WEBRTC_DEFINE_int(cn_wb, + TestConfig::default_cn_wb(), + "RTP payload type for comfort noise (16 kHz)"); +WEBRTC_DEFINE_int(cn_swb32, + TestConfig::default_cn_swb32(), + "RTP payload type for comfort noise (32 kHz)"); +WEBRTC_DEFINE_int(cn_swb48, + TestConfig::default_cn_swb48(), + "RTP payload type for comfort noise (48 kHz)"); +WEBRTC_DEFINE_string(replacement_audio_file, + "", + "A PCM file that will be used to populate dummy" + " RTP packets"); +WEBRTC_DEFINE_string( + ssrc, + "", + "Only use packets with this SSRC (decimal or hex, the latter " + "starting with 0x)"); +WEBRTC_DEFINE_int(audio_level, + TestConfig::default_audio_level(), + "Extension ID for audio level (RFC 6464)"); +WEBRTC_DEFINE_int(abs_send_time, + TestConfig::default_abs_send_time(), + "Extension ID for absolute sender time"); +WEBRTC_DEFINE_int(transport_seq_no, + TestConfig::default_transport_seq_no(), + "Extension ID for transport sequence number"); +WEBRTC_DEFINE_int(video_content_type, + TestConfig::default_video_content_type(), + "Extension ID for video content type"); +WEBRTC_DEFINE_int(video_timing, + TestConfig::default_video_timing(), + "Extension ID for video timing"); +WEBRTC_DEFINE_bool(matlabplot, + false, + "Generates a matlab script for plotting the delay profile"); +WEBRTC_DEFINE_bool(pythonplot, + false, + "Generates a python script for plotting the delay profile"); +WEBRTC_DEFINE_bool(textlog, + false, + "Generates a text log describing the simulation on a " + "step-by-step basis."); +WEBRTC_DEFINE_bool(concealment_events, false, "Prints concealment events"); +WEBRTC_DEFINE_int(max_nr_packets_in_buffer, + TestConfig::default_max_nr_packets_in_buffer(), + "Maximum allowed number of packets in the buffer"); +WEBRTC_DEFINE_bool(enable_fast_accelerate, + false, + "Enables jitter buffer fast accelerate"); + +// Parses the input string for a valid SSRC (at the start of the string). If a +// valid SSRC is found, it is written to the output variable |ssrc|, and true is +// returned. Otherwise, false is returned. +bool ParseSsrc(const std::string& str, uint32_t* ssrc) { + if (str.empty()) + return true; + int base = 10; + // Look for "0x" or "0X" at the start and change base to 16 if found. + if ((str.compare(0, 2, "0x") == 0) || (str.compare(0, 2, "0X") == 0)) + base = 16; + errno = 0; + char* end_ptr; + unsigned long value = strtoul(str.c_str(), &end_ptr, base); // NOLINT + if (value == ULONG_MAX && errno == ERANGE) + return false; // Value out of range for unsigned long. + if (sizeof(unsigned long) > sizeof(uint32_t) && value > 0xFFFFFFFF) // NOLINT + return false; // Value out of range for uint32_t. + if (end_ptr - str.c_str() < static_cast(str.length())) + return false; // Part of the string was not parsed. + *ssrc = static_cast(value); + return true; +} + +static bool ValidateExtensionId(int value) { + if (value > 0 && value <= 255) // Value is ok. + return true; + printf("Extension ID must be between 1 and 255, not %d\n", + static_cast(value)); + return false; +} + +// Flag validators. +bool ValidatePayloadType(int value) { + if (value >= 0 && value <= 127) // Value is ok. + return true; + printf("Payload type must be between 0 and 127, not %d\n", + static_cast(value)); + return false; +} + +bool ValidateSsrcValue(const std::string& str) { + uint32_t dummy_ssrc; + if (ParseSsrc(str, &dummy_ssrc)) // Value is ok. + return true; + printf("Invalid SSRC: %s\n", str.c_str()); + return false; +} + +void PrintCodecMappingEntry(const char* codec, int flag) { + std::cout << codec << ": " << flag << std::endl; +} + +void PrintCodecMapping() { + PrintCodecMappingEntry("PCM-u", FLAG_pcmu); + PrintCodecMappingEntry("PCM-a", FLAG_pcma); + PrintCodecMappingEntry("iLBC", FLAG_ilbc); + PrintCodecMappingEntry("iSAC", FLAG_isac); + PrintCodecMappingEntry("iSAC-swb (32 kHz)", FLAG_isac_swb); + PrintCodecMappingEntry("Opus", FLAG_opus); + PrintCodecMappingEntry("PCM16b-nb (8 kHz)", FLAG_pcm16b); + PrintCodecMappingEntry("PCM16b-wb (16 kHz)", FLAG_pcm16b_wb); + PrintCodecMappingEntry("PCM16b-swb32 (32 kHz)", FLAG_pcm16b_swb32); + PrintCodecMappingEntry("PCM16b-swb48 (48 kHz)", FLAG_pcm16b_swb48); + PrintCodecMappingEntry("G.722", FLAG_g722); + PrintCodecMappingEntry("AVT/DTMF (8 kHz)", FLAG_avt); + PrintCodecMappingEntry("AVT/DTMF (16 kHz)", FLAG_avt_16); + PrintCodecMappingEntry("AVT/DTMF (32 kHz)", FLAG_avt_32); + PrintCodecMappingEntry("AVT/DTMF (48 kHz)", FLAG_avt_48); + PrintCodecMappingEntry("redundant audio (RED)", FLAG_red); + PrintCodecMappingEntry("comfort noise (8 kHz)", FLAG_cn_nb); + PrintCodecMappingEntry("comfort noise (16 kHz)", FLAG_cn_wb); + PrintCodecMappingEntry("comfort noise (32 kHz)", FLAG_cn_swb32); + PrintCodecMappingEntry("comfort noise (48 kHz)", FLAG_cn_swb48); +} + +} // namespace int main(int argc, char* argv[]) { webrtc::test::NetEqTestFactory factory; @@ -48,21 +231,85 @@ int main(int argc, char* argv[]) { exit(0); } if (FLAG_codec_map) { - factory.PrintCodecMap(); + PrintCodecMapping(); + exit(0); } if (argc != 3) { - if (FLAG_codec_map) { - // We have already printed the codec map. Just end the program. - exit(0); - } // Print usage information. std::cout << usage; exit(0); } + RTC_CHECK(ValidatePayloadType(FLAG_pcmu)); + RTC_CHECK(ValidatePayloadType(FLAG_pcma)); + RTC_CHECK(ValidatePayloadType(FLAG_ilbc)); + RTC_CHECK(ValidatePayloadType(FLAG_isac)); + RTC_CHECK(ValidatePayloadType(FLAG_isac_swb)); + RTC_CHECK(ValidatePayloadType(FLAG_opus)); + RTC_CHECK(ValidatePayloadType(FLAG_pcm16b)); + RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_wb)); + RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_swb32)); + RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_swb48)); + RTC_CHECK(ValidatePayloadType(FLAG_g722)); + RTC_CHECK(ValidatePayloadType(FLAG_avt)); + RTC_CHECK(ValidatePayloadType(FLAG_avt_16)); + RTC_CHECK(ValidatePayloadType(FLAG_avt_32)); + RTC_CHECK(ValidatePayloadType(FLAG_avt_48)); + RTC_CHECK(ValidatePayloadType(FLAG_red)); + RTC_CHECK(ValidatePayloadType(FLAG_cn_nb)); + RTC_CHECK(ValidatePayloadType(FLAG_cn_wb)); + RTC_CHECK(ValidatePayloadType(FLAG_cn_swb32)); + RTC_CHECK(ValidatePayloadType(FLAG_cn_swb48)); + RTC_CHECK(ValidateSsrcValue(FLAG_ssrc)); + RTC_CHECK(ValidateExtensionId(FLAG_audio_level)); + RTC_CHECK(ValidateExtensionId(FLAG_abs_send_time)); + RTC_CHECK(ValidateExtensionId(FLAG_transport_seq_no)); + RTC_CHECK(ValidateExtensionId(FLAG_video_content_type)); + RTC_CHECK(ValidateExtensionId(FLAG_video_timing)); + webrtc::test::ValidateFieldTrialsStringOrDie(FLAG_force_fieldtrials); webrtc::field_trial::InitFieldTrialsFromString(FLAG_force_fieldtrials); + webrtc::test::NetEqTestFactory::Config config; + config.pcmu = FLAG_pcmu; + config.pcma = FLAG_pcma; + config.ilbc = FLAG_ilbc; + config.isac = FLAG_isac; + config.isac_swb = FLAG_isac_swb; + config.opus = FLAG_opus; + config.pcm16b = FLAG_pcm16b; + config.pcm16b_wb = FLAG_pcm16b_wb; + config.pcm16b_swb32 = FLAG_pcm16b_swb32; + config.pcm16b_swb48 = FLAG_pcm16b_swb48; + config.g722 = FLAG_g722; + config.avt = FLAG_avt; + config.avt_16 = FLAG_avt_16; + config.avt_32 = FLAG_avt_32; + config.avt_48 = FLAG_avt_48; + config.red = FLAG_red; + config.cn_nb = FLAG_cn_nb; + config.cn_wb = FLAG_cn_wb; + config.cn_swb32 = FLAG_cn_swb32; + config.cn_swb48 = FLAG_cn_swb48; + config.replacement_audio_file = FLAG_replacement_audio_file; + config.audio_level = FLAG_audio_level; + config.abs_send_time = FLAG_abs_send_time; + config.transport_seq_no = FLAG_transport_seq_no; + config.video_content_type = FLAG_video_content_type; + config.video_timing = FLAG_video_timing; + config.matlabplot = FLAG_matlabplot; + config.pythonplot = FLAG_pythonplot; + config.textlog = FLAG_textlog; + config.concealment_events = FLAG_concealment_events; + config.max_nr_packets_in_buffer = FLAG_max_nr_packets_in_buffer; + config.enable_fast_accelerate = FLAG_enable_fast_accelerate; + // Check if an SSRC value was provided. + if (strlen(FLAG_ssrc) > 0) { + uint32_t ssrc; + RTC_CHECK(ParseSsrc(FLAG_ssrc, &ssrc)) << "Flag verification has failed."; + config.ssrc_filter = absl::make_optional(ssrc); + } + std::unique_ptr test = - factory.InitializeTest(argv[1], argv[2]); + factory.InitializeTest(argv[1], argv[2], config); test->Run(); return 0; } diff --git a/modules/audio_coding/neteq/tools/neteq_test_factory.cc b/modules/audio_coding/neteq/tools/neteq_test_factory.cc index accaaed35c..1d38bc4420 100644 --- a/modules/audio_coding/neteq/tools/neteq_test_factory.cc +++ b/modules/audio_coding/neteq/tools/neteq_test_factory.cc @@ -46,157 +46,24 @@ namespace webrtc { namespace test { namespace { -// Parses the input string for a valid SSRC (at the start of the string). If a -// valid SSRC is found, it is written to the output variable |ssrc|, and true is -// returned. Otherwise, false is returned. -bool ParseSsrc(const std::string& str, uint32_t* ssrc) { - if (str.empty()) - return true; - int base = 10; - // Look for "0x" or "0X" at the start and change base to 16 if found. - if ((str.compare(0, 2, "0x") == 0) || (str.compare(0, 2, "0X") == 0)) - base = 16; - errno = 0; - char* end_ptr; - unsigned long value = strtoul(str.c_str(), &end_ptr, base); // NOLINT - if (value == ULONG_MAX && errno == ERANGE) - return false; // Value out of range for unsigned long. - if (sizeof(unsigned long) > sizeof(uint32_t) && value > 0xFFFFFFFF) // NOLINT - return false; // Value out of range for uint32_t. - if (end_ptr - str.c_str() < static_cast(str.length())) - return false; // Part of the string was not parsed. - *ssrc = static_cast(value); - return true; -} - -// Flag validators. -bool ValidatePayloadType(int value) { - if (value >= 0 && value <= 127) // Value is ok. - return true; - printf("Payload type must be between 0 and 127, not %d\n", - static_cast(value)); - return false; -} - -bool ValidateSsrcValue(const std::string& str) { - uint32_t dummy_ssrc; - if (ParseSsrc(str, &dummy_ssrc)) // Value is ok. - return true; - printf("Invalid SSRC: %s\n", str.c_str()); - return false; -} - -static bool ValidateExtensionId(int value) { - if (value > 0 && value <= 255) // Value is ok. - return true; - printf("Extension ID must be between 1 and 255, not %d\n", - static_cast(value)); - return false; -} - -// Define command line flags. -WEBRTC_DEFINE_int(pcmu, 0, "RTP payload type for PCM-u"); -WEBRTC_DEFINE_int(pcma, 8, "RTP payload type for PCM-a"); -WEBRTC_DEFINE_int(ilbc, 102, "RTP payload type for iLBC"); -WEBRTC_DEFINE_int(isac, 103, "RTP payload type for iSAC"); -WEBRTC_DEFINE_int(isac_swb, 104, "RTP payload type for iSAC-swb (32 kHz)"); -WEBRTC_DEFINE_int(opus, 111, "RTP payload type for Opus"); -WEBRTC_DEFINE_int(pcm16b, 93, "RTP payload type for PCM16b-nb (8 kHz)"); -WEBRTC_DEFINE_int(pcm16b_wb, 94, "RTP payload type for PCM16b-wb (16 kHz)"); -WEBRTC_DEFINE_int(pcm16b_swb32, - 95, - "RTP payload type for PCM16b-swb32 (32 kHz)"); -WEBRTC_DEFINE_int(pcm16b_swb48, - 96, - "RTP payload type for PCM16b-swb48 (48 kHz)"); -WEBRTC_DEFINE_int(g722, 9, "RTP payload type for G.722"); -WEBRTC_DEFINE_int(avt, 106, "RTP payload type for AVT/DTMF (8 kHz)"); -WEBRTC_DEFINE_int(avt_16, 114, "RTP payload type for AVT/DTMF (16 kHz)"); -WEBRTC_DEFINE_int(avt_32, 115, "RTP payload type for AVT/DTMF (32 kHz)"); -WEBRTC_DEFINE_int(avt_48, 116, "RTP payload type for AVT/DTMF (48 kHz)"); -WEBRTC_DEFINE_int(red, 117, "RTP payload type for redundant audio (RED)"); -WEBRTC_DEFINE_int(cn_nb, 13, "RTP payload type for comfort noise (8 kHz)"); -WEBRTC_DEFINE_int(cn_wb, 98, "RTP payload type for comfort noise (16 kHz)"); -WEBRTC_DEFINE_int(cn_swb32, 99, "RTP payload type for comfort noise (32 kHz)"); -WEBRTC_DEFINE_int(cn_swb48, 100, "RTP payload type for comfort noise (48 kHz)"); -WEBRTC_DEFINE_string(replacement_audio_file, - "", - "A PCM file that will be used to populate " - "dummy" - " RTP packets"); -WEBRTC_DEFINE_string( - ssrc, - "", - "Only use packets with this SSRC (decimal or hex, the latter " - "starting with 0x)"); -WEBRTC_DEFINE_int(audio_level, 1, "Extension ID for audio level (RFC 6464)"); -WEBRTC_DEFINE_int(abs_send_time, 3, "Extension ID for absolute sender time"); -WEBRTC_DEFINE_int(transport_seq_no, - 5, - "Extension ID for transport sequence number"); -WEBRTC_DEFINE_int(video_content_type, 7, "Extension ID for video content type"); -WEBRTC_DEFINE_int(video_timing, 8, "Extension ID for video timing"); -WEBRTC_DEFINE_bool(matlabplot, - false, - "Generates a matlab script for plotting the delay profile"); -WEBRTC_DEFINE_bool(pythonplot, - false, - "Generates a python script for plotting the delay profile"); -WEBRTC_DEFINE_bool(textlog, - false, - "Generates a text log describing the simulation on a " - "step-by-step basis."); -WEBRTC_DEFINE_bool(concealment_events, false, "Prints concealment events"); -WEBRTC_DEFINE_int(max_nr_packets_in_buffer, - 50, - "Maximum allowed number of packets in the buffer"); -WEBRTC_DEFINE_bool(enable_fast_accelerate, - false, - "Enables jitter buffer fast accelerate"); - -void PrintCodecMappingEntry(const char* codec, int flag) { - std::cout << codec << ": " << flag << std::endl; -} - -void PrintCodecMapping() { - PrintCodecMappingEntry("PCM-u", FLAG_pcmu); - PrintCodecMappingEntry("PCM-a", FLAG_pcma); - PrintCodecMappingEntry("iLBC", FLAG_ilbc); - PrintCodecMappingEntry("iSAC", FLAG_isac); - PrintCodecMappingEntry("iSAC-swb (32 kHz)", FLAG_isac_swb); - PrintCodecMappingEntry("Opus", FLAG_opus); - PrintCodecMappingEntry("PCM16b-nb (8 kHz)", FLAG_pcm16b); - PrintCodecMappingEntry("PCM16b-wb (16 kHz)", FLAG_pcm16b_wb); - PrintCodecMappingEntry("PCM16b-swb32 (32 kHz)", FLAG_pcm16b_swb32); - PrintCodecMappingEntry("PCM16b-swb48 (48 kHz)", FLAG_pcm16b_swb48); - PrintCodecMappingEntry("G.722", FLAG_g722); - PrintCodecMappingEntry("AVT/DTMF (8 kHz)", FLAG_avt); - PrintCodecMappingEntry("AVT/DTMF (16 kHz)", FLAG_avt_16); - PrintCodecMappingEntry("AVT/DTMF (32 kHz)", FLAG_avt_32); - PrintCodecMappingEntry("AVT/DTMF (48 kHz)", FLAG_avt_48); - PrintCodecMappingEntry("redundant audio (RED)", FLAG_red); - PrintCodecMappingEntry("comfort noise (8 kHz)", FLAG_cn_nb); - PrintCodecMappingEntry("comfort noise (16 kHz)", FLAG_cn_wb); - PrintCodecMappingEntry("comfort noise (32 kHz)", FLAG_cn_swb32); - PrintCodecMappingEntry("comfort noise (48 kHz)", FLAG_cn_swb48); -} - -absl::optional CodecSampleRate(uint8_t payload_type) { - if (payload_type == FLAG_pcmu || payload_type == FLAG_pcma || - payload_type == FLAG_ilbc || payload_type == FLAG_pcm16b || - payload_type == FLAG_cn_nb || payload_type == FLAG_avt) +absl::optional CodecSampleRate( + uint8_t payload_type, + webrtc::test::NetEqTestFactory::Config config) { + if (payload_type == config.pcmu || payload_type == config.pcma || + payload_type == config.ilbc || payload_type == config.pcm16b || + payload_type == config.cn_nb || payload_type == config.avt) return 8000; - if (payload_type == FLAG_isac || payload_type == FLAG_pcm16b_wb || - payload_type == FLAG_g722 || payload_type == FLAG_cn_wb || - payload_type == FLAG_avt_16) + if (payload_type == config.isac || payload_type == config.pcm16b_wb || + payload_type == config.g722 || payload_type == config.cn_wb || + payload_type == config.avt_16) return 16000; - if (payload_type == FLAG_isac_swb || payload_type == FLAG_pcm16b_swb32 || - payload_type == FLAG_cn_swb32 || payload_type == FLAG_avt_32) + if (payload_type == config.isac_swb || payload_type == config.pcm16b_swb32 || + payload_type == config.cn_swb32 || payload_type == config.avt_32) return 32000; - if (payload_type == FLAG_opus || payload_type == FLAG_pcm16b_swb48 || - payload_type == FLAG_cn_swb48 || payload_type == FLAG_avt_48) + if (payload_type == config.opus || payload_type == config.pcm16b_swb48 || + payload_type == config.cn_swb48 || payload_type == config.avt_48) return 48000; - if (payload_type == FLAG_red) + if (payload_type == config.red) return 0; return absl::nullopt; } @@ -234,66 +101,31 @@ class SsrcSwitchDetector : public NetEqPostInsertPacket { }; NetEqTestFactory::NetEqTestFactory() = default; - NetEqTestFactory::~NetEqTestFactory() = default; -void NetEqTestFactory::PrintCodecMap() { - PrintCodecMapping(); -} +NetEqTestFactory::Config::Config() = default; +NetEqTestFactory::Config::Config(const Config& other) = default; +NetEqTestFactory::Config::~Config() = default; std::unique_ptr NetEqTestFactory::InitializeTest( std::string input_file_name, - std::string output_file_name) { - RTC_CHECK(ValidatePayloadType(FLAG_pcmu)); - RTC_CHECK(ValidatePayloadType(FLAG_pcma)); - RTC_CHECK(ValidatePayloadType(FLAG_ilbc)); - RTC_CHECK(ValidatePayloadType(FLAG_isac)); - RTC_CHECK(ValidatePayloadType(FLAG_isac_swb)); - RTC_CHECK(ValidatePayloadType(FLAG_opus)); - RTC_CHECK(ValidatePayloadType(FLAG_pcm16b)); - RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_wb)); - RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_swb32)); - RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_swb48)); - RTC_CHECK(ValidatePayloadType(FLAG_g722)); - RTC_CHECK(ValidatePayloadType(FLAG_avt)); - RTC_CHECK(ValidatePayloadType(FLAG_avt_16)); - RTC_CHECK(ValidatePayloadType(FLAG_avt_32)); - RTC_CHECK(ValidatePayloadType(FLAG_avt_48)); - RTC_CHECK(ValidatePayloadType(FLAG_red)); - RTC_CHECK(ValidatePayloadType(FLAG_cn_nb)); - RTC_CHECK(ValidatePayloadType(FLAG_cn_wb)); - RTC_CHECK(ValidatePayloadType(FLAG_cn_swb32)); - RTC_CHECK(ValidatePayloadType(FLAG_cn_swb48)); - RTC_CHECK(ValidateSsrcValue(FLAG_ssrc)); - RTC_CHECK(ValidateExtensionId(FLAG_audio_level)); - RTC_CHECK(ValidateExtensionId(FLAG_abs_send_time)); - RTC_CHECK(ValidateExtensionId(FLAG_transport_seq_no)); - RTC_CHECK(ValidateExtensionId(FLAG_video_content_type)); - RTC_CHECK(ValidateExtensionId(FLAG_video_timing)); - + std::string output_file_name, + const Config& config) { // Gather RTP header extensions in a map. NetEqPacketSourceInput::RtpHeaderExtensionMap rtp_ext_map = { - {FLAG_audio_level, kRtpExtensionAudioLevel}, - {FLAG_abs_send_time, kRtpExtensionAbsoluteSendTime}, - {FLAG_transport_seq_no, kRtpExtensionTransportSequenceNumber}, - {FLAG_video_content_type, kRtpExtensionVideoContentType}, - {FLAG_video_timing, kRtpExtensionVideoTiming}}; - - absl::optional ssrc_filter; - // Check if an SSRC value was provided. - if (strlen(FLAG_ssrc) > 0) { - uint32_t ssrc; - RTC_CHECK(ParseSsrc(FLAG_ssrc, &ssrc)) << "Flag verification has failed."; - ssrc_filter = ssrc; - } + {config.audio_level, kRtpExtensionAudioLevel}, + {config.abs_send_time, kRtpExtensionAbsoluteSendTime}, + {config.transport_seq_no, kRtpExtensionTransportSequenceNumber}, + {config.video_content_type, kRtpExtensionVideoContentType}, + {config.video_timing, kRtpExtensionVideoTiming}}; std::unique_ptr input; if (RtpFileSource::ValidRtpDump(input_file_name) || RtpFileSource::ValidPcap(input_file_name)) { - input.reset( - new NetEqRtpDumpInput(input_file_name, rtp_ext_map, ssrc_filter)); + input.reset(new NetEqRtpDumpInput(input_file_name, rtp_ext_map, + config.ssrc_filter)); } else { - input.reset(new NetEqEventLogInput(input_file_name, ssrc_filter)); + input.reset(new NetEqEventLogInput(input_file_name, config.ssrc_filter)); } std::cout << "Input file: " << input_file_name << std::endl; @@ -305,7 +137,7 @@ std::unique_ptr NetEqTestFactory::InitializeTest( std::set> discarded_pt_and_ssrc; while (absl::optional first_rtp_header = input->NextHeader()) { RTC_DCHECK(first_rtp_header); - sample_rate_hz = CodecSampleRate(first_rtp_header->payloadType); + sample_rate_hz = CodecSampleRate(first_rtp_header->payloadType, config); if (sample_rate_hz) { std::cout << "Found valid packet with payload type " << static_cast(first_rtp_header->payloadType) @@ -354,7 +186,7 @@ std::unique_ptr NetEqTestFactory::InitializeTest( CreateBuiltinAudioDecoderFactory(); // Check if a replacement audio file was provided. - if (strlen(FLAG_replacement_audio_file) > 0) { + if (config.replacement_audio_file.size() > 0) { // Find largest unused payload type. int replacement_pt = 127; while (codecs.find(replacement_pt) != codecs.end()) { @@ -371,22 +203,25 @@ std::unique_ptr NetEqTestFactory::InitializeTest( }; std::set cn_types = std_set_int32_to_uint8( - {FLAG_cn_nb, FLAG_cn_wb, FLAG_cn_swb32, FLAG_cn_swb48}); - std::set forbidden_types = std_set_int32_to_uint8( - {FLAG_g722, FLAG_red, FLAG_avt, FLAG_avt_16, FLAG_avt_32, FLAG_avt_48}); + {config.cn_nb, config.cn_wb, config.cn_swb32, config.cn_swb48}); + std::set forbidden_types = + std_set_int32_to_uint8({config.g722, config.red, config.avt, + config.avt_16, config.avt_32, config.avt_48}); input.reset(new NetEqReplacementInput(std::move(input), replacement_pt, cn_types, forbidden_types)); // Note that capture-by-copy implies that the lambda captures the value of // decoder_factory before it's reassigned on the left-hand side. decoder_factory = new rtc::RefCountedObject( - [decoder_factory](const SdpAudioFormat& format, - absl::optional codec_pair_id) { + [decoder_factory, config]( + const SdpAudioFormat& format, + absl::optional codec_pair_id) { std::unique_ptr decoder = decoder_factory->MakeAudioDecoder(format, codec_pair_id); if (!decoder && format.name == "replacement") { decoder = absl::make_unique( - absl::make_unique(FLAG_replacement_audio_file), + absl::make_unique( + config.replacement_audio_file), format.clockrate_hz, format.num_channels > 1); } return decoder; @@ -399,26 +234,26 @@ std::unique_ptr NetEqTestFactory::InitializeTest( // Create a text log file if needed. std::unique_ptr text_log; - if (FLAG_textlog) { + if (config.textlog) { text_log = absl::make_unique(output_file_name + ".text_log.txt"); } NetEqTest::Callbacks callbacks; - stats_plotter_.reset(new NetEqStatsPlotter(FLAG_matlabplot, FLAG_pythonplot, - FLAG_concealment_events, - output_file_name)); + stats_plotter_.reset( + new NetEqStatsPlotter(config.matlabplot, config.pythonplot, + config.concealment_events, output_file_name)); ssrc_switch_detector_.reset( new SsrcSwitchDetector(stats_plotter_->stats_getter()->delay_analyzer())); callbacks.post_insert_packet = ssrc_switch_detector_.get(); callbacks.get_audio_callback = stats_plotter_->stats_getter(); callbacks.simulation_ended_callback = stats_plotter_.get(); - NetEq::Config config; - config.sample_rate_hz = *sample_rate_hz; - config.max_packets_in_buffer = FLAG_max_nr_packets_in_buffer; - config.enable_fast_accelerate = FLAG_enable_fast_accelerate; - return absl::make_unique(config, decoder_factory, codecs, + NetEq::Config neteq_config; + neteq_config.sample_rate_hz = *sample_rate_hz; + neteq_config.max_packets_in_buffer = config.max_nr_packets_in_buffer; + neteq_config.enable_fast_accelerate = config.enable_fast_accelerate; + return absl::make_unique(neteq_config, decoder_factory, codecs, std::move(text_log), std::move(input), std::move(output), callbacks); } diff --git a/modules/audio_coding/neteq/tools/neteq_test_factory.h b/modules/audio_coding/neteq/tools/neteq_test_factory.h index f853c1dedd..dbcdf1a71a 100644 --- a/modules/audio_coding/neteq/tools/neteq_test_factory.h +++ b/modules/audio_coding/neteq/tools/neteq_test_factory.h @@ -14,6 +14,7 @@ #include #include +#include "absl/types/optional.h" #include "modules/audio_coding/neteq/tools/neteq_test.h" namespace webrtc { @@ -29,9 +30,107 @@ class NetEqTestFactory { public: NetEqTestFactory(); ~NetEqTestFactory(); - void PrintCodecMap(); + struct Config { + Config(); + Config(const Config& other); + ~Config(); + // RTP payload type for PCM-u. + static constexpr int default_pcmu() { return 0; } + int pcmu = default_pcmu(); + // RTP payload type for PCM-a. + static constexpr int default_pcma() { return 8; } + int pcma = default_pcma(); + // RTP payload type for iLBC. + static constexpr int default_ilbc() { return 102; } + int ilbc = default_ilbc(); + // RTP payload type for iSAC. + static constexpr int default_isac() { return 103; } + int isac = default_isac(); + // RTP payload type for iSAC-swb (32 kHz). + static constexpr int default_isac_swb() { return 104; } + int isac_swb = default_isac_swb(); + // RTP payload type for Opus. + static constexpr int default_opus() { return 111; } + int opus = default_opus(); + // RTP payload type for PCM16b-nb (8 kHz). + static constexpr int default_pcm16b() { return 93; } + int pcm16b = default_pcm16b(); + // RTP payload type for PCM16b-wb (16 kHz). + static constexpr int default_pcm16b_wb() { return 94; } + int pcm16b_wb = default_pcm16b_wb(); + // RTP payload type for PCM16b-swb32 (32 kHz). + static constexpr int default_pcm16b_swb32() { return 95; } + int pcm16b_swb32 = default_pcm16b_swb32(); + // RTP payload type for PCM16b-swb48 (48 kHz). + static constexpr int default_pcm16b_swb48() { return 96; } + int pcm16b_swb48 = default_pcm16b_swb48(); + // RTP payload type for G.722. + static constexpr int default_g722() { return 9; } + int g722 = default_g722(); + // RTP payload type for AVT/DTMF (8 kHz). + static constexpr int default_avt() { return 106; } + int avt = default_avt(); + // RTP payload type for AVT/DTMF (16 kHz). + static constexpr int default_avt_16() { return 114; } + int avt_16 = default_avt_16(); + // RTP payload type for AVT/DTMF (32 kHz). + static constexpr int default_avt_32() { return 115; } + int avt_32 = default_avt_32(); + // RTP payload type for AVT/DTMF (48 kHz). + static constexpr int default_avt_48() { return 116; } + int avt_48 = default_avt_48(); + // RTP payload type for redundant audio (RED). + static constexpr int default_red() { return 117; } + int red = default_red(); + // RTP payload type for comfort noise (8 kHz). + static constexpr int default_cn_nb() { return 13; } + int cn_nb = default_cn_nb(); + // RTP payload type for comfort noise (16 kHz). + static constexpr int default_cn_wb() { return 98; } + int cn_wb = default_cn_wb(); + // RTP payload type for comfort noise (32 kHz). + static constexpr int default_cn_swb32() { return 99; } + int cn_swb32 = default_cn_swb32(); + // RTP payload type for comfort noise (48 kHz). + static constexpr int default_cn_swb48() { return 100; } + int cn_swb48 = default_cn_swb48(); + // A PCM file that will be used to populate dummy RTP packets. + std::string replacement_audio_file; + // Only use packets with this SSRC. + absl::optional ssrc_filter; + // Extension ID for audio level (RFC 6464). + static constexpr int default_audio_level() { return 1; } + int audio_level = default_audio_level(); + // Extension ID for absolute sender time. + static constexpr int default_abs_send_time() { return 3; } + int abs_send_time = default_abs_send_time(); + // Extension ID for transport sequence number. + static constexpr int default_transport_seq_no() { return 5; } + int transport_seq_no = default_transport_seq_no(); + // Extension ID for video content type. + static constexpr int default_video_content_type() { return 7; } + int video_content_type = default_video_content_type(); + // Extension ID for video timing. + static constexpr int default_video_timing() { return 8; } + int video_timing = default_video_timing(); + // Generate a matlab script for plotting the delay profile. + bool matlabplot = false; + // Generates a python script for plotting the delay profile. + bool pythonplot = false; + // Generates a text log describing the simulation on a step-by-step basis. + bool textlog = false; + // Prints concealment events. + bool concealment_events = false; + // Maximum allowed number of packets in the buffer. + static constexpr int default_max_nr_packets_in_buffer() { return 50; } + int max_nr_packets_in_buffer = default_max_nr_packets_in_buffer(); + // Enables jitter buffer fast accelerate. + bool enable_fast_accelerate = false; + }; + std::unique_ptr InitializeTest(std::string input_filename, - std::string output_filename); + std::string output_filename, + const Config& config); private: std::unique_ptr ssrc_switch_detector_;