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:
Ivo Creusen
2019-02-26 13:03:21 +01:00
committed by Commit Bot
parent 5983585ee8
commit ba7886b076
5 changed files with 419 additions and 221 deletions

View File

@ -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",

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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_;