Move command line flags out of NetEqTestFactory
This replaces the use of command-line flags with the use of a config struct. This makes it easier for non command-line applications to use the NetEqTestFactory to run simulations. Bug: webrtc:10337 Change-Id: I24533bf206e70e12db9af8d9675769c1ff7c7d48 Reviewed-on: https://webrtc-review.googlesource.com/c/123600 Reviewed-by: Pablo Barrera González <barrerap@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Commit-Queue: Ivo Creusen <ivoc@webrtc.org> Cr-Commit-Position: refs/heads/master@{#26887}
This commit is contained in:
@ -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",
|
||||
|
||||
@ -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<ptrdiff_t>(str.length()))
|
||||
return false; // Part of the string was not parsed.
|
||||
*ssrc = static_cast<uint32_t>(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<int>(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<int>(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<webrtc::test::NetEqTest> test =
|
||||
factory.InitializeTest(argv[1], argv[2]);
|
||||
factory.InitializeTest(argv[1], argv[2], config);
|
||||
test->Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -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<ptrdiff_t>(str.length()))
|
||||
return false; // Part of the string was not parsed.
|
||||
*ssrc = static_cast<uint32_t>(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<int>(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<int>(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<int> 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<int> 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<NetEqTest> 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<uint32_t> 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<NetEqInput> 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<NetEqTest> NetEqTestFactory::InitializeTest(
|
||||
std::set<std::pair<int, uint32_t>> discarded_pt_and_ssrc;
|
||||
while (absl::optional<RTPHeader> 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<int>(first_rtp_header->payloadType)
|
||||
@ -354,7 +186,7 @@ std::unique_ptr<NetEqTest> 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<NetEqTest> NetEqTestFactory::InitializeTest(
|
||||
};
|
||||
|
||||
std::set<uint8_t> cn_types = std_set_int32_to_uint8(
|
||||
{FLAG_cn_nb, FLAG_cn_wb, FLAG_cn_swb32, FLAG_cn_swb48});
|
||||
std::set<uint8_t> 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<uint8_t> 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<FunctionAudioDecoderFactory>(
|
||||
[decoder_factory](const SdpAudioFormat& format,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id) {
|
||||
[decoder_factory, config](
|
||||
const SdpAudioFormat& format,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id) {
|
||||
std::unique_ptr<AudioDecoder> decoder =
|
||||
decoder_factory->MakeAudioDecoder(format, codec_pair_id);
|
||||
if (!decoder && format.name == "replacement") {
|
||||
decoder = absl::make_unique<FakeDecodeFromFile>(
|
||||
absl::make_unique<InputAudioFile>(FLAG_replacement_audio_file),
|
||||
absl::make_unique<InputAudioFile>(
|
||||
config.replacement_audio_file),
|
||||
format.clockrate_hz, format.num_channels > 1);
|
||||
}
|
||||
return decoder;
|
||||
@ -399,26 +234,26 @@ std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTest(
|
||||
|
||||
// Create a text log file if needed.
|
||||
std::unique_ptr<std::ofstream> text_log;
|
||||
if (FLAG_textlog) {
|
||||
if (config.textlog) {
|
||||
text_log =
|
||||
absl::make_unique<std::ofstream>(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<NetEqTest>(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<NetEqTest>(neteq_config, decoder_factory, codecs,
|
||||
std::move(text_log), std::move(input),
|
||||
std::move(output), callbacks);
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#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<uint32_t> 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<NetEqTest> InitializeTest(std::string input_filename,
|
||||
std::string output_filename);
|
||||
std::string output_filename,
|
||||
const Config& config);
|
||||
|
||||
private:
|
||||
std::unique_ptr<SsrcSwitchDetector> ssrc_switch_detector_;
|
||||
|
||||
Reference in New Issue
Block a user