blob: 36c03b8eef0132c7d300b9948ca5e3868280127c [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Ivo Creusenf81b0f12018-09-11 10:30:58 +020011#include <iostream>
12#include <string>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000013
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "modules/audio_coding/neteq/tools/neteq_test.h"
Ivo Creusen55de08e2018-09-03 11:49:27 +020015#include "modules/audio_coding/neteq/tools/neteq_test_factory.h"
Ivo Creusenf81b0f12018-09-11 10:30:58 +020016#include "rtc_base/flags.h"
Mirko Bonadei17f48782018-09-28 08:51:10 +020017#include "system_wrappers/include/field_trial.h"
Ivo Creusenf81b0f12018-09-11 10:30:58 +020018#include "test/field_trial.h"
19
Ivo Creusenba7886b2019-02-26 13:03:21 +010020namespace {
21
22using TestConfig = webrtc::test::NetEqTestFactory::Config;
23
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020024WEBRTC_DEFINE_bool(codec_map,
25 false,
26 "Prints the mapping between RTP payload type and "
27 "codec");
28WEBRTC_DEFINE_string(
Ivo Creusenf81b0f12018-09-11 10:30:58 +020029 force_fieldtrials,
30 "",
31 "Field trials control experimental feature code which can be forced. "
32 "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/"
33 " will assign the group Enable to field trial WebRTC-FooFeature.");
Mirko Bonadei2dfa9982018-10-18 11:35:32 +020034WEBRTC_DEFINE_bool(help, false, "Prints this message");
Ivo Creusenba7886b2019-02-26 13:03:21 +010035// Define command line flags.
36WEBRTC_DEFINE_int(pcmu,
37 TestConfig::default_pcmu(),
38 "RTP payload type for PCM-u");
39WEBRTC_DEFINE_int(pcma,
40 TestConfig::default_pcma(),
41 "RTP payload type for PCM-a");
42WEBRTC_DEFINE_int(ilbc,
43 TestConfig::default_ilbc(),
44 "RTP payload type for iLBC");
45WEBRTC_DEFINE_int(isac,
46 TestConfig::default_isac(),
47 "RTP payload type for iSAC");
48WEBRTC_DEFINE_int(isac_swb,
49 TestConfig::default_isac_swb(),
50 "RTP payload type for iSAC-swb (32 kHz)");
51WEBRTC_DEFINE_int(opus,
52 TestConfig::default_opus(),
53 "RTP payload type for Opus");
54WEBRTC_DEFINE_int(pcm16b,
55 TestConfig::default_pcm16b(),
56 "RTP payload type for PCM16b-nb (8 kHz)");
57WEBRTC_DEFINE_int(pcm16b_wb,
58 TestConfig::default_pcm16b_wb(),
59 "RTP payload type for PCM16b-wb (16 kHz)");
60WEBRTC_DEFINE_int(pcm16b_swb32,
61 TestConfig::default_pcm16b_swb32(),
62 "RTP payload type for PCM16b-swb32 (32 kHz)");
63WEBRTC_DEFINE_int(pcm16b_swb48,
64 TestConfig::default_pcm16b_swb48(),
65 "RTP payload type for PCM16b-swb48 (48 kHz)");
66WEBRTC_DEFINE_int(g722,
67 TestConfig::default_g722(),
68 "RTP payload type for G.722");
69WEBRTC_DEFINE_int(avt,
70 TestConfig::default_avt(),
71 "RTP payload type for AVT/DTMF (8 kHz)");
72WEBRTC_DEFINE_int(avt_16,
73 TestConfig::default_avt_16(),
74 "RTP payload type for AVT/DTMF (16 kHz)");
75WEBRTC_DEFINE_int(avt_32,
76 TestConfig::default_avt_32(),
77 "RTP payload type for AVT/DTMF (32 kHz)");
78WEBRTC_DEFINE_int(avt_48,
79 TestConfig::default_avt_48(),
80 "RTP payload type for AVT/DTMF (48 kHz)");
81WEBRTC_DEFINE_int(red,
82 TestConfig::default_red(),
83 "RTP payload type for redundant audio (RED)");
84WEBRTC_DEFINE_int(cn_nb,
85 TestConfig::default_cn_nb(),
86 "RTP payload type for comfort noise (8 kHz)");
87WEBRTC_DEFINE_int(cn_wb,
88 TestConfig::default_cn_wb(),
89 "RTP payload type for comfort noise (16 kHz)");
90WEBRTC_DEFINE_int(cn_swb32,
91 TestConfig::default_cn_swb32(),
92 "RTP payload type for comfort noise (32 kHz)");
93WEBRTC_DEFINE_int(cn_swb48,
94 TestConfig::default_cn_swb48(),
95 "RTP payload type for comfort noise (48 kHz)");
96WEBRTC_DEFINE_string(replacement_audio_file,
97 "",
98 "A PCM file that will be used to populate dummy"
99 " RTP packets");
100WEBRTC_DEFINE_string(
101 ssrc,
102 "",
103 "Only use packets with this SSRC (decimal or hex, the latter "
104 "starting with 0x)");
105WEBRTC_DEFINE_int(audio_level,
106 TestConfig::default_audio_level(),
107 "Extension ID for audio level (RFC 6464)");
108WEBRTC_DEFINE_int(abs_send_time,
109 TestConfig::default_abs_send_time(),
110 "Extension ID for absolute sender time");
111WEBRTC_DEFINE_int(transport_seq_no,
112 TestConfig::default_transport_seq_no(),
113 "Extension ID for transport sequence number");
114WEBRTC_DEFINE_int(video_content_type,
115 TestConfig::default_video_content_type(),
116 "Extension ID for video content type");
117WEBRTC_DEFINE_int(video_timing,
118 TestConfig::default_video_timing(),
119 "Extension ID for video timing");
120WEBRTC_DEFINE_bool(matlabplot,
121 false,
122 "Generates a matlab script for plotting the delay profile");
123WEBRTC_DEFINE_bool(pythonplot,
124 false,
125 "Generates a python script for plotting the delay profile");
126WEBRTC_DEFINE_bool(textlog,
127 false,
128 "Generates a text log describing the simulation on a "
129 "step-by-step basis.");
130WEBRTC_DEFINE_bool(concealment_events, false, "Prints concealment events");
131WEBRTC_DEFINE_int(max_nr_packets_in_buffer,
132 TestConfig::default_max_nr_packets_in_buffer(),
133 "Maximum allowed number of packets in the buffer");
134WEBRTC_DEFINE_bool(enable_fast_accelerate,
135 false,
136 "Enables jitter buffer fast accelerate");
137
138// Parses the input string for a valid SSRC (at the start of the string). If a
139// valid SSRC is found, it is written to the output variable |ssrc|, and true is
140// returned. Otherwise, false is returned.
141bool ParseSsrc(const std::string& str, uint32_t* ssrc) {
142 if (str.empty())
143 return true;
144 int base = 10;
145 // Look for "0x" or "0X" at the start and change base to 16 if found.
146 if ((str.compare(0, 2, "0x") == 0) || (str.compare(0, 2, "0X") == 0))
147 base = 16;
148 errno = 0;
149 char* end_ptr;
150 unsigned long value = strtoul(str.c_str(), &end_ptr, base); // NOLINT
151 if (value == ULONG_MAX && errno == ERANGE)
152 return false; // Value out of range for unsigned long.
153 if (sizeof(unsigned long) > sizeof(uint32_t) && value > 0xFFFFFFFF) // NOLINT
154 return false; // Value out of range for uint32_t.
155 if (end_ptr - str.c_str() < static_cast<ptrdiff_t>(str.length()))
156 return false; // Part of the string was not parsed.
157 *ssrc = static_cast<uint32_t>(value);
158 return true;
159}
160
161static bool ValidateExtensionId(int value) {
162 if (value > 0 && value <= 255) // Value is ok.
163 return true;
164 printf("Extension ID must be between 1 and 255, not %d\n",
165 static_cast<int>(value));
166 return false;
167}
168
169// Flag validators.
170bool ValidatePayloadType(int value) {
171 if (value >= 0 && value <= 127) // Value is ok.
172 return true;
173 printf("Payload type must be between 0 and 127, not %d\n",
174 static_cast<int>(value));
175 return false;
176}
177
178bool ValidateSsrcValue(const std::string& str) {
179 uint32_t dummy_ssrc;
180 if (ParseSsrc(str, &dummy_ssrc)) // Value is ok.
181 return true;
182 printf("Invalid SSRC: %s\n", str.c_str());
183 return false;
184}
185
186void PrintCodecMappingEntry(const char* codec, int flag) {
187 std::cout << codec << ": " << flag << std::endl;
188}
189
190void PrintCodecMapping() {
191 PrintCodecMappingEntry("PCM-u", FLAG_pcmu);
192 PrintCodecMappingEntry("PCM-a", FLAG_pcma);
193 PrintCodecMappingEntry("iLBC", FLAG_ilbc);
194 PrintCodecMappingEntry("iSAC", FLAG_isac);
195 PrintCodecMappingEntry("iSAC-swb (32 kHz)", FLAG_isac_swb);
196 PrintCodecMappingEntry("Opus", FLAG_opus);
197 PrintCodecMappingEntry("PCM16b-nb (8 kHz)", FLAG_pcm16b);
198 PrintCodecMappingEntry("PCM16b-wb (16 kHz)", FLAG_pcm16b_wb);
199 PrintCodecMappingEntry("PCM16b-swb32 (32 kHz)", FLAG_pcm16b_swb32);
200 PrintCodecMappingEntry("PCM16b-swb48 (48 kHz)", FLAG_pcm16b_swb48);
201 PrintCodecMappingEntry("G.722", FLAG_g722);
202 PrintCodecMappingEntry("AVT/DTMF (8 kHz)", FLAG_avt);
203 PrintCodecMappingEntry("AVT/DTMF (16 kHz)", FLAG_avt_16);
204 PrintCodecMappingEntry("AVT/DTMF (32 kHz)", FLAG_avt_32);
205 PrintCodecMappingEntry("AVT/DTMF (48 kHz)", FLAG_avt_48);
206 PrintCodecMappingEntry("redundant audio (RED)", FLAG_red);
207 PrintCodecMappingEntry("comfort noise (8 kHz)", FLAG_cn_nb);
208 PrintCodecMappingEntry("comfort noise (16 kHz)", FLAG_cn_wb);
209 PrintCodecMappingEntry("comfort noise (32 kHz)", FLAG_cn_swb32);
210 PrintCodecMappingEntry("comfort noise (48 kHz)", FLAG_cn_swb48);
211}
212
213} // namespace
henrik.lundin303d3e12016-05-26 05:56:03 -0700214
215int main(int argc, char* argv[]) {
Ivo Creusen55de08e2018-09-03 11:49:27 +0200216 webrtc::test::NetEqTestFactory factory;
Ivo Creusenf81b0f12018-09-11 10:30:58 +0200217 std::string program_name = argv[0];
218 std::string usage =
219 "Tool for decoding an RTP dump file using NetEq.\n"
220 "Run " +
221 program_name +
222 " --help for usage.\n"
223 "Example usage:\n" +
Ivo Creusenc4b391a2019-03-12 14:27:54 +0000224 program_name + " input.rtp output.{pcm, wav}\n";
Ivo Creusenf81b0f12018-09-11 10:30:58 +0200225 if (rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, true)) {
226 exit(1);
227 }
228 if (FLAG_help) {
229 std::cout << usage;
230 rtc::FlagList::Print(nullptr, false);
231 exit(0);
232 }
233 if (FLAG_codec_map) {
Ivo Creusenba7886b2019-02-26 13:03:21 +0100234 PrintCodecMapping();
235 exit(0);
Ivo Creusenf81b0f12018-09-11 10:30:58 +0200236 }
Ivo Creusenc4b391a2019-03-12 14:27:54 +0000237 if (argc != 3) {
Ivo Creusenf81b0f12018-09-11 10:30:58 +0200238 // Print usage information.
239 std::cout << usage;
240 exit(0);
241 }
Ivo Creusenba7886b2019-02-26 13:03:21 +0100242 RTC_CHECK(ValidatePayloadType(FLAG_pcmu));
243 RTC_CHECK(ValidatePayloadType(FLAG_pcma));
244 RTC_CHECK(ValidatePayloadType(FLAG_ilbc));
245 RTC_CHECK(ValidatePayloadType(FLAG_isac));
246 RTC_CHECK(ValidatePayloadType(FLAG_isac_swb));
247 RTC_CHECK(ValidatePayloadType(FLAG_opus));
248 RTC_CHECK(ValidatePayloadType(FLAG_pcm16b));
249 RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_wb));
250 RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_swb32));
251 RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_swb48));
252 RTC_CHECK(ValidatePayloadType(FLAG_g722));
253 RTC_CHECK(ValidatePayloadType(FLAG_avt));
254 RTC_CHECK(ValidatePayloadType(FLAG_avt_16));
255 RTC_CHECK(ValidatePayloadType(FLAG_avt_32));
256 RTC_CHECK(ValidatePayloadType(FLAG_avt_48));
257 RTC_CHECK(ValidatePayloadType(FLAG_red));
258 RTC_CHECK(ValidatePayloadType(FLAG_cn_nb));
259 RTC_CHECK(ValidatePayloadType(FLAG_cn_wb));
260 RTC_CHECK(ValidatePayloadType(FLAG_cn_swb32));
261 RTC_CHECK(ValidatePayloadType(FLAG_cn_swb48));
262 RTC_CHECK(ValidateSsrcValue(FLAG_ssrc));
263 RTC_CHECK(ValidateExtensionId(FLAG_audio_level));
264 RTC_CHECK(ValidateExtensionId(FLAG_abs_send_time));
265 RTC_CHECK(ValidateExtensionId(FLAG_transport_seq_no));
266 RTC_CHECK(ValidateExtensionId(FLAG_video_content_type));
267 RTC_CHECK(ValidateExtensionId(FLAG_video_timing));
268
Ivo Creusenf81b0f12018-09-11 10:30:58 +0200269 webrtc::test::ValidateFieldTrialsStringOrDie(FLAG_force_fieldtrials);
270 webrtc::field_trial::InitFieldTrialsFromString(FLAG_force_fieldtrials);
Ivo Creusenba7886b2019-02-26 13:03:21 +0100271 webrtc::test::NetEqTestFactory::Config config;
272 config.pcmu = FLAG_pcmu;
273 config.pcma = FLAG_pcma;
274 config.ilbc = FLAG_ilbc;
275 config.isac = FLAG_isac;
276 config.isac_swb = FLAG_isac_swb;
277 config.opus = FLAG_opus;
278 config.pcm16b = FLAG_pcm16b;
279 config.pcm16b_wb = FLAG_pcm16b_wb;
280 config.pcm16b_swb32 = FLAG_pcm16b_swb32;
281 config.pcm16b_swb48 = FLAG_pcm16b_swb48;
282 config.g722 = FLAG_g722;
283 config.avt = FLAG_avt;
284 config.avt_16 = FLAG_avt_16;
285 config.avt_32 = FLAG_avt_32;
286 config.avt_48 = FLAG_avt_48;
287 config.red = FLAG_red;
288 config.cn_nb = FLAG_cn_nb;
289 config.cn_wb = FLAG_cn_wb;
290 config.cn_swb32 = FLAG_cn_swb32;
291 config.cn_swb48 = FLAG_cn_swb48;
292 config.replacement_audio_file = FLAG_replacement_audio_file;
293 config.audio_level = FLAG_audio_level;
294 config.abs_send_time = FLAG_abs_send_time;
295 config.transport_seq_no = FLAG_transport_seq_no;
296 config.video_content_type = FLAG_video_content_type;
297 config.video_timing = FLAG_video_timing;
298 config.matlabplot = FLAG_matlabplot;
299 config.pythonplot = FLAG_pythonplot;
Ivo Creusenc4b391a2019-03-12 14:27:54 +0000300 config.textlog = FLAG_textlog;
Ivo Creusenba7886b2019-02-26 13:03:21 +0100301 config.concealment_events = FLAG_concealment_events;
302 config.max_nr_packets_in_buffer = FLAG_max_nr_packets_in_buffer;
303 config.enable_fast_accelerate = FLAG_enable_fast_accelerate;
304 // Check if an SSRC value was provided.
305 if (strlen(FLAG_ssrc) > 0) {
306 uint32_t ssrc;
307 RTC_CHECK(ParseSsrc(FLAG_ssrc, &ssrc)) << "Flag verification has failed.";
308 config.ssrc_filter = absl::make_optional(ssrc);
309 }
310
Ivo Creusenc4b391a2019-03-12 14:27:54 +0000311 std::unique_ptr<webrtc::test::NetEqTest> test =
312 factory.InitializeTest(argv[1], argv[2], config);
Ivo Creusen55de08e2018-09-03 11:49:27 +0200313 test->Run();
314 return 0;
henrik.lundin303d3e12016-05-26 05:56:03 -0700315}