2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
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.
11 // TODO(hlundin): The functionality in this file should be moved into one or
16 #include <limits.h> // For ULONG_MAX returned by strtoul.
18 #include <stdlib.h> // For strtoul.
24 #include "google/gflags.h"
25 #include "webrtc/base/checks.h"
26 #include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h"
27 #include "webrtc/modules/audio_coding/neteq/interface/neteq.h"
28 #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
29 #include "webrtc/modules/audio_coding/neteq/tools/packet.h"
30 #include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h"
31 #include "webrtc/modules/interface/module_common_types.h"
32 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
33 #include "webrtc/system_wrappers/interface/trace.h"
34 #include "webrtc/test/testsupport/fileutils.h"
35 #include "webrtc/typedefs.h"
38 using webrtc::WebRtcRTPHeader;
41 // Parses the input string for a valid SSRC (at the start of the string). If a
42 // valid SSRC is found, it is written to the output variable |ssrc|, and true is
43 // returned. Otherwise, false is returned.
44 bool ParseSsrc(const std::string& str, uint32_t* ssrc) {
48 // Look for "0x" or "0X" at the start and change base to 16 if found.
49 if ((str.compare(0, 2, "0x") == 0) || (str.compare(0, 2, "0X") == 0))
53 unsigned long value = strtoul(str.c_str(), &end_ptr, base);
54 if (value == ULONG_MAX && errno == ERANGE)
55 return false; // Value out of range for unsigned long.
56 if (sizeof(unsigned long) > sizeof(uint32_t) && value > 0xFFFFFFFF)
57 return false; // Value out of range for uint32_t.
58 if (end_ptr - str.c_str() < static_cast<ptrdiff_t>(str.length()))
59 return false; // Part of the string was not parsed.
60 *ssrc = static_cast<uint32_t>(value);
67 static bool ValidatePayloadType(const char* flagname, int32_t value) {
68 if (value >= 0 && value <= 127) // Value is ok.
70 printf("Invalid value for --%s: %d\n", flagname, static_cast<int>(value));
74 static bool ValidateSsrcValue(const char* flagname, const std::string& str) {
76 return ParseSsrc(str, &dummy_ssrc);
79 // Define command line flags.
80 DEFINE_int32(pcmu, 0, "RTP payload type for PCM-u");
81 static const bool pcmu_dummy =
82 google::RegisterFlagValidator(&FLAGS_pcmu, &ValidatePayloadType);
83 DEFINE_int32(pcma, 8, "RTP payload type for PCM-a");
84 static const bool pcma_dummy =
85 google::RegisterFlagValidator(&FLAGS_pcma, &ValidatePayloadType);
86 DEFINE_int32(ilbc, 102, "RTP payload type for iLBC");
87 static const bool ilbc_dummy =
88 google::RegisterFlagValidator(&FLAGS_ilbc, &ValidatePayloadType);
89 DEFINE_int32(isac, 103, "RTP payload type for iSAC");
90 static const bool isac_dummy =
91 google::RegisterFlagValidator(&FLAGS_isac, &ValidatePayloadType);
92 DEFINE_int32(isac_swb, 104, "RTP payload type for iSAC-swb (32 kHz)");
93 static const bool isac_swb_dummy =
94 google::RegisterFlagValidator(&FLAGS_isac_swb, &ValidatePayloadType);
95 DEFINE_int32(opus, 111, "RTP payload type for Opus");
96 static const bool opus_dummy =
97 google::RegisterFlagValidator(&FLAGS_opus, &ValidatePayloadType);
98 DEFINE_int32(pcm16b, 93, "RTP payload type for PCM16b-nb (8 kHz)");
99 static const bool pcm16b_dummy =
100 google::RegisterFlagValidator(&FLAGS_pcm16b, &ValidatePayloadType);
101 DEFINE_int32(pcm16b_wb, 94, "RTP payload type for PCM16b-wb (16 kHz)");
102 static const bool pcm16b_wb_dummy =
103 google::RegisterFlagValidator(&FLAGS_pcm16b_wb, &ValidatePayloadType);
104 DEFINE_int32(pcm16b_swb32, 95, "RTP payload type for PCM16b-swb32 (32 kHz)");
105 static const bool pcm16b_swb32_dummy =
106 google::RegisterFlagValidator(&FLAGS_pcm16b_swb32, &ValidatePayloadType);
107 DEFINE_int32(pcm16b_swb48, 96, "RTP payload type for PCM16b-swb48 (48 kHz)");
108 static const bool pcm16b_swb48_dummy =
109 google::RegisterFlagValidator(&FLAGS_pcm16b_swb48, &ValidatePayloadType);
110 DEFINE_int32(g722, 9, "RTP payload type for G.722");
111 static const bool g722_dummy =
112 google::RegisterFlagValidator(&FLAGS_g722, &ValidatePayloadType);
113 DEFINE_int32(avt, 106, "RTP payload type for AVT/DTMF");
114 static const bool avt_dummy =
115 google::RegisterFlagValidator(&FLAGS_avt, &ValidatePayloadType);
116 DEFINE_int32(red, 117, "RTP payload type for redundant audio (RED)");
117 static const bool red_dummy =
118 google::RegisterFlagValidator(&FLAGS_red, &ValidatePayloadType);
119 DEFINE_int32(cn_nb, 13, "RTP payload type for comfort noise (8 kHz)");
120 static const bool cn_nb_dummy =
121 google::RegisterFlagValidator(&FLAGS_cn_nb, &ValidatePayloadType);
122 DEFINE_int32(cn_wb, 98, "RTP payload type for comfort noise (16 kHz)");
123 static const bool cn_wb_dummy =
124 google::RegisterFlagValidator(&FLAGS_cn_wb, &ValidatePayloadType);
125 DEFINE_int32(cn_swb32, 99, "RTP payload type for comfort noise (32 kHz)");
126 static const bool cn_swb32_dummy =
127 google::RegisterFlagValidator(&FLAGS_cn_swb32, &ValidatePayloadType);
128 DEFINE_int32(cn_swb48, 100, "RTP payload type for comfort noise (48 kHz)");
129 static const bool cn_swb48_dummy =
130 google::RegisterFlagValidator(&FLAGS_cn_swb48, &ValidatePayloadType);
131 DEFINE_bool(codec_map, false, "Prints the mapping between RTP payload type and "
133 DEFINE_string(replacement_audio_file, "",
134 "A PCM file that will be used to populate ""dummy"" RTP packets");
137 "Only use packets with this SSRC (decimal or hex, the latter "
138 "starting with 0x)");
139 static const bool hex_ssrc_dummy =
140 google::RegisterFlagValidator(&FLAGS_ssrc, &ValidateSsrcValue);
142 // Declaring helper functions (defined further down in this file).
143 std::string CodecName(webrtc::NetEqDecoder codec);
144 void RegisterPayloadTypes(NetEq* neteq);
145 void PrintCodecMapping();
146 size_t ReplacePayload(webrtc::test::InputAudioFile* replacement_audio_file,
147 webrtc::scoped_ptr<int16_t[]>* replacement_audio,
148 webrtc::scoped_ptr<uint8_t[]>* payload,
149 size_t* payload_mem_size_bytes,
150 size_t* frame_size_samples,
151 WebRtcRTPHeader* rtp_header,
152 const webrtc::test::Packet* next_packet);
153 int CodecSampleRate(uint8_t payload_type);
154 int CodecTimestampRate(uint8_t payload_type);
155 bool IsComfortNosie(uint8_t payload_type);
157 int main(int argc, char* argv[]) {
158 static const int kMaxChannels = 5;
159 static const int kMaxSamplesPerMs = 48000 / 1000;
160 static const int kOutputBlockSizeMs = 10;
162 std::string program_name = argv[0];
163 std::string usage = "Tool for decoding an RTP dump file using NetEq.\n"
164 "Run " + program_name + " --helpshort for usage.\n"
165 "Example usage:\n" + program_name +
166 " input.rtp output.pcm\n";
167 google::SetUsageMessage(usage);
168 google::ParseCommandLineFlags(&argc, &argv, true);
170 if (FLAGS_codec_map) {
175 if (FLAGS_codec_map) {
176 // We have already printed the codec map. Just end the program.
179 // Print usage information.
180 std::cout << google::ProgramUsage();
184 printf("Input file: %s\n", argv[1]);
185 webrtc::scoped_ptr<webrtc::test::RtpFileSource> file_source(
186 webrtc::test::RtpFileSource::Create(argv[1]));
187 assert(file_source.get());
189 // Check if an SSRC value was provided.
190 if (!FLAGS_ssrc.empty()) {
192 CHECK(ParseSsrc(FLAGS_ssrc, &ssrc)) << "Flag verification has failed.";
193 file_source->SelectSsrc(ssrc);
196 FILE* out_file = fopen(argv[2], "wb");
198 std::cerr << "Cannot open output file " << argv[2] << std::endl;
201 std::cout << "Output file: " << argv[2] << std::endl;
203 // Check if a replacement audio file was provided, and if so, open it.
204 bool replace_payload = false;
205 webrtc::scoped_ptr<webrtc::test::InputAudioFile> replacement_audio_file;
206 if (!FLAGS_replacement_audio_file.empty()) {
207 replacement_audio_file.reset(
208 new webrtc::test::InputAudioFile(FLAGS_replacement_audio_file));
209 replace_payload = true;
213 webrtc::Trace::CreateTrace();
214 webrtc::Trace::SetTraceFile((webrtc::test::OutputPath() +
215 "neteq_trace.txt").c_str());
216 webrtc::Trace::set_level_filter(webrtc::kTraceAll);
218 // Initialize NetEq instance.
219 int sample_rate_hz = 16000;
220 NetEq::Config config;
221 config.sample_rate_hz = sample_rate_hz;
222 NetEq* neteq = NetEq::Create(config);
223 RegisterPayloadTypes(neteq);
225 // Read first packet.
226 webrtc::scoped_ptr<webrtc::test::Packet> packet(file_source->NextPacket());
229 "Warning: input file is empty, or the filters did not match any "
231 webrtc::Trace::ReturnTrace();
234 bool packet_available = true;
236 // Set up variables for audio replacement if needed.
237 webrtc::scoped_ptr<webrtc::test::Packet> next_packet;
238 bool next_packet_available = false;
239 size_t input_frame_size_timestamps = 0;
240 webrtc::scoped_ptr<int16_t[]> replacement_audio;
241 webrtc::scoped_ptr<uint8_t[]> payload;
242 size_t payload_mem_size_bytes = 0;
243 if (replace_payload) {
244 // Initially assume that the frame size is 30 ms at the initial sample rate.
245 // This value will be replaced with the correct one as soon as two
246 // consecutive packets are found.
247 input_frame_size_timestamps = 30 * sample_rate_hz / 1000;
248 replacement_audio.reset(new int16_t[input_frame_size_timestamps]);
249 payload_mem_size_bytes = 2 * input_frame_size_timestamps;
250 payload.reset(new uint8_t[payload_mem_size_bytes]);
251 next_packet.reset(file_source->NextPacket());
253 next_packet_available = true;
256 // This is the main simulation loop.
257 // Set the simulation clock to start immediately with the first packet.
258 int time_now_ms = packet->time_ms();
259 int next_input_time_ms = time_now_ms;
260 int next_output_time_ms = time_now_ms;
261 if (time_now_ms % kOutputBlockSizeMs != 0) {
262 // Make sure that next_output_time_ms is rounded up to the next multiple
263 // of kOutputBlockSizeMs. (Legacy bit-exactness.)
264 next_output_time_ms +=
265 kOutputBlockSizeMs - time_now_ms % kOutputBlockSizeMs;
267 while (packet_available) {
268 // Check if it is time to insert packet.
269 while (time_now_ms >= next_input_time_ms && packet_available) {
270 assert(packet->virtual_payload_length_bytes() > 0);
272 WebRtcRTPHeader rtp_header;
273 packet->ConvertHeader(&rtp_header);
274 const uint8_t* payload_ptr = packet->payload();
275 size_t payload_len = packet->payload_length_bytes();
276 if (replace_payload) {
277 payload_len = ReplacePayload(replacement_audio_file.get(),
280 &payload_mem_size_bytes,
281 &input_frame_size_timestamps,
284 payload_ptr = payload.get();
287 neteq->InsertPacket(rtp_header,
289 static_cast<int>(payload_len),
290 packet->time_ms() * sample_rate_hz / 1000);
291 if (error != NetEq::kOK) {
292 if (neteq->LastError() == NetEq::kUnknownRtpPayloadType) {
293 std::cerr << "RTP Payload type "
294 << static_cast<int>(rtp_header.header.payloadType)
295 << " is unknown." << std::endl;
296 std::cerr << "Use --codec_map to view default mapping." << std::endl;
297 std::cerr << "Use --helpshort for information on how to make custom "
298 "mappings." << std::endl;
300 std::cerr << "InsertPacket returned error code " << neteq->LastError()
302 std::cerr << "Header data:" << std::endl;
303 std::cerr << " PT = "
304 << static_cast<int>(rtp_header.header.payloadType)
306 std::cerr << " SN = " << rtp_header.header.sequenceNumber
308 std::cerr << " TS = " << rtp_header.header.timestamp << std::endl;
312 // Get next packet from file.
313 webrtc::test::Packet* temp_packet = file_source->NextPacket();
315 packet.reset(temp_packet);
317 packet_available = false;
319 if (replace_payload) {
320 // At this point |packet| contains the packet *after* |next_packet|.
321 // Swap Packet objects between |packet| and |next_packet|.
322 packet.swap(next_packet);
323 // Swap the status indicators unless they're already the same.
324 if (packet_available != next_packet_available) {
325 packet_available = !packet_available;
326 next_packet_available = !next_packet_available;
329 next_input_time_ms = packet->time_ms();
332 // Check if it is time to get output audio.
333 if (time_now_ms >= next_output_time_ms) {
334 static const int kOutDataLen = kOutputBlockSizeMs * kMaxSamplesPerMs *
336 int16_t out_data[kOutDataLen];
338 int samples_per_channel;
339 int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel,
340 &num_channels, NULL);
341 if (error != NetEq::kOK) {
342 std::cerr << "GetAudio returned error code " <<
343 neteq->LastError() << std::endl;
345 // Calculate sample rate from output size.
346 sample_rate_hz = 1000 * samples_per_channel / kOutputBlockSizeMs;
350 // TODO(hlundin): Make writing to file optional.
351 size_t write_len = samples_per_channel * num_channels;
352 if (fwrite(out_data, sizeof(out_data[0]), write_len, out_file) !=
354 std::cerr << "Error while writing to file" << std::endl;
355 webrtc::Trace::ReturnTrace();
358 next_output_time_ms += kOutputBlockSizeMs;
360 // Advance time to next event.
361 time_now_ms = std::min(next_input_time_ms, next_output_time_ms);
364 std::cout << "Simulation done" << std::endl;
368 webrtc::Trace::ReturnTrace();
375 // Maps a codec type to a printable name string.
376 std::string CodecName(webrtc::NetEqDecoder codec) {
378 case webrtc::kDecoderPCMu:
380 case webrtc::kDecoderPCMa:
382 case webrtc::kDecoderILBC:
384 case webrtc::kDecoderISAC:
386 case webrtc::kDecoderISACswb:
387 return "iSAC-swb (32 kHz)";
388 case webrtc::kDecoderOpus:
390 case webrtc::kDecoderPCM16B:
391 return "PCM16b-nb (8 kHz)";
392 case webrtc::kDecoderPCM16Bwb:
393 return "PCM16b-wb (16 kHz)";
394 case webrtc::kDecoderPCM16Bswb32kHz:
395 return "PCM16b-swb32 (32 kHz)";
396 case webrtc::kDecoderPCM16Bswb48kHz:
397 return "PCM16b-swb48 (48 kHz)";
398 case webrtc::kDecoderG722:
400 case webrtc::kDecoderRED:
401 return "redundant audio (RED)";
402 case webrtc::kDecoderAVT:
404 case webrtc::kDecoderCNGnb:
405 return "comfort noise (8 kHz)";
406 case webrtc::kDecoderCNGwb:
407 return "comfort noise (16 kHz)";
408 case webrtc::kDecoderCNGswb32kHz:
409 return "comfort noise (32 kHz)";
410 case webrtc::kDecoderCNGswb48kHz:
411 return "comfort noise (48 kHz)";
418 // Registers all decoders in |neteq|.
419 void RegisterPayloadTypes(NetEq* neteq) {
422 error = neteq->RegisterPayloadType(webrtc::kDecoderPCMu, FLAGS_pcmu);
424 std::cerr << "Cannot register payload type " << FLAGS_pcmu <<
425 " as " << CodecName(webrtc::kDecoderPCMu).c_str() << std::endl;
428 error = neteq->RegisterPayloadType(webrtc::kDecoderPCMa, FLAGS_pcma);
430 std::cerr << "Cannot register payload type " << FLAGS_pcma <<
431 " as " << CodecName(webrtc::kDecoderPCMa).c_str() << std::endl;
434 error = neteq->RegisterPayloadType(webrtc::kDecoderILBC, FLAGS_ilbc);
436 std::cerr << "Cannot register payload type " << FLAGS_ilbc <<
437 " as " << CodecName(webrtc::kDecoderILBC).c_str() << std::endl;
440 error = neteq->RegisterPayloadType(webrtc::kDecoderISAC, FLAGS_isac);
442 std::cerr << "Cannot register payload type " << FLAGS_isac <<
443 " as " << CodecName(webrtc::kDecoderISAC).c_str() << std::endl;
446 error = neteq->RegisterPayloadType(webrtc::kDecoderISACswb, FLAGS_isac_swb);
448 std::cerr << "Cannot register payload type " << FLAGS_isac_swb <<
449 " as " << CodecName(webrtc::kDecoderISACswb).c_str() << std::endl;
452 error = neteq->RegisterPayloadType(webrtc::kDecoderOpus, FLAGS_opus);
454 std::cerr << "Cannot register payload type " << FLAGS_opus << " as "
455 << CodecName(webrtc::kDecoderOpus).c_str() << std::endl;
458 error = neteq->RegisterPayloadType(webrtc::kDecoderPCM16B, FLAGS_pcm16b);
460 std::cerr << "Cannot register payload type " << FLAGS_pcm16b <<
461 " as " << CodecName(webrtc::kDecoderPCM16B).c_str() << std::endl;
464 error = neteq->RegisterPayloadType(webrtc::kDecoderPCM16Bwb,
467 std::cerr << "Cannot register payload type " << FLAGS_pcm16b_wb <<
468 " as " << CodecName(webrtc::kDecoderPCM16Bwb).c_str() << std::endl;
471 error = neteq->RegisterPayloadType(webrtc::kDecoderPCM16Bswb32kHz,
474 std::cerr << "Cannot register payload type " << FLAGS_pcm16b_swb32 <<
475 " as " << CodecName(webrtc::kDecoderPCM16Bswb32kHz).c_str() <<
479 error = neteq->RegisterPayloadType(webrtc::kDecoderPCM16Bswb48kHz,
482 std::cerr << "Cannot register payload type " << FLAGS_pcm16b_swb48 <<
483 " as " << CodecName(webrtc::kDecoderPCM16Bswb48kHz).c_str() <<
487 error = neteq->RegisterPayloadType(webrtc::kDecoderG722, FLAGS_g722);
489 std::cerr << "Cannot register payload type " << FLAGS_g722 <<
490 " as " << CodecName(webrtc::kDecoderG722).c_str() << std::endl;
493 error = neteq->RegisterPayloadType(webrtc::kDecoderAVT, FLAGS_avt);
495 std::cerr << "Cannot register payload type " << FLAGS_avt <<
496 " as " << CodecName(webrtc::kDecoderAVT).c_str() << std::endl;
499 error = neteq->RegisterPayloadType(webrtc::kDecoderRED, FLAGS_red);
501 std::cerr << "Cannot register payload type " << FLAGS_red <<
502 " as " << CodecName(webrtc::kDecoderRED).c_str() << std::endl;
505 error = neteq->RegisterPayloadType(webrtc::kDecoderCNGnb, FLAGS_cn_nb);
507 std::cerr << "Cannot register payload type " << FLAGS_cn_nb <<
508 " as " << CodecName(webrtc::kDecoderCNGnb).c_str() << std::endl;
511 error = neteq->RegisterPayloadType(webrtc::kDecoderCNGwb, FLAGS_cn_wb);
513 std::cerr << "Cannot register payload type " << FLAGS_cn_wb <<
514 " as " << CodecName(webrtc::kDecoderCNGwb).c_str() << std::endl;
517 error = neteq->RegisterPayloadType(webrtc::kDecoderCNGswb32kHz,
520 std::cerr << "Cannot register payload type " << FLAGS_cn_swb32 <<
521 " as " << CodecName(webrtc::kDecoderCNGswb32kHz).c_str() << std::endl;
524 error = neteq->RegisterPayloadType(webrtc::kDecoderCNGswb48kHz,
527 std::cerr << "Cannot register payload type " << FLAGS_cn_swb48 <<
528 " as " << CodecName(webrtc::kDecoderCNGswb48kHz).c_str() << std::endl;
533 void PrintCodecMapping() {
534 std::cout << CodecName(webrtc::kDecoderPCMu).c_str() << ": " << FLAGS_pcmu <<
536 std::cout << CodecName(webrtc::kDecoderPCMa).c_str() << ": " << FLAGS_pcma <<
538 std::cout << CodecName(webrtc::kDecoderILBC).c_str() << ": " << FLAGS_ilbc <<
540 std::cout << CodecName(webrtc::kDecoderISAC).c_str() << ": " << FLAGS_isac <<
542 std::cout << CodecName(webrtc::kDecoderISACswb).c_str() << ": " <<
543 FLAGS_isac_swb << std::endl;
544 std::cout << CodecName(webrtc::kDecoderOpus).c_str() << ": " << FLAGS_opus
546 std::cout << CodecName(webrtc::kDecoderPCM16B).c_str() << ": " <<
547 FLAGS_pcm16b << std::endl;
548 std::cout << CodecName(webrtc::kDecoderPCM16Bwb).c_str() << ": " <<
549 FLAGS_pcm16b_wb << std::endl;
550 std::cout << CodecName(webrtc::kDecoderPCM16Bswb32kHz).c_str() << ": " <<
551 FLAGS_pcm16b_swb32 << std::endl;
552 std::cout << CodecName(webrtc::kDecoderPCM16Bswb48kHz).c_str() << ": " <<
553 FLAGS_pcm16b_swb48 << std::endl;
554 std::cout << CodecName(webrtc::kDecoderG722).c_str() << ": " << FLAGS_g722 <<
556 std::cout << CodecName(webrtc::kDecoderAVT).c_str() << ": " << FLAGS_avt <<
558 std::cout << CodecName(webrtc::kDecoderRED).c_str() << ": " << FLAGS_red <<
560 std::cout << CodecName(webrtc::kDecoderCNGnb).c_str() << ": " <<
561 FLAGS_cn_nb << std::endl;
562 std::cout << CodecName(webrtc::kDecoderCNGwb).c_str() << ": " <<
563 FLAGS_cn_wb << std::endl;
564 std::cout << CodecName(webrtc::kDecoderCNGswb32kHz).c_str() << ": " <<
565 FLAGS_cn_swb32 << std::endl;
566 std::cout << CodecName(webrtc::kDecoderCNGswb48kHz).c_str() << ": " <<
567 FLAGS_cn_swb48 << std::endl;
570 size_t ReplacePayload(webrtc::test::InputAudioFile* replacement_audio_file,
571 webrtc::scoped_ptr<int16_t[]>* replacement_audio,
572 webrtc::scoped_ptr<uint8_t[]>* payload,
573 size_t* payload_mem_size_bytes,
574 size_t* frame_size_samples,
575 WebRtcRTPHeader* rtp_header,
576 const webrtc::test::Packet* next_packet) {
577 size_t payload_len = 0;
579 if (IsComfortNosie(rtp_header->header.payloadType)) {
580 // If CNG, simply insert a zero-energy one-byte payload.
581 if (*payload_mem_size_bytes < 1) {
582 (*payload).reset(new uint8_t[1]);
583 *payload_mem_size_bytes = 1;
585 (*payload)[0] = 127; // Max attenuation of CNG.
588 assert(next_packet->virtual_payload_length_bytes() > 0);
589 // Check if payload length has changed.
590 if (next_packet->header().sequenceNumber ==
591 rtp_header->header.sequenceNumber + 1) {
592 if (*frame_size_samples !=
593 next_packet->header().timestamp - rtp_header->header.timestamp) {
594 *frame_size_samples =
595 next_packet->header().timestamp - rtp_header->header.timestamp;
596 (*replacement_audio).reset(
597 new int16_t[*frame_size_samples]);
598 *payload_mem_size_bytes = 2 * *frame_size_samples;
599 (*payload).reset(new uint8_t[*payload_mem_size_bytes]);
603 assert((*replacement_audio).get());
604 if (CodecTimestampRate(rtp_header->header.payloadType) !=
605 CodecSampleRate(rtp_header->header.payloadType) ||
606 rtp_header->header.payloadType == FLAGS_red ||
607 rtp_header->header.payloadType == FLAGS_avt) {
608 // Some codecs have different sample and timestamp rates. And neither
609 // RED nor DTMF is supported for replacement.
610 std::cerr << "Codec not supported for audio replacement." <<
612 webrtc::Trace::ReturnTrace();
615 assert(*frame_size_samples > 0);
616 if (!replacement_audio_file->Read(*frame_size_samples,
617 (*replacement_audio).get())) {
618 std::cerr << "Could not read replacement audio file." << std::endl;
619 webrtc::Trace::ReturnTrace();
622 // Encode it as PCM16.
623 assert((*payload).get());
624 payload_len = WebRtcPcm16b_Encode((*replacement_audio).get(),
625 static_cast<int16_t>(*frame_size_samples),
627 assert(payload_len == 2 * *frame_size_samples);
628 // Change payload type to PCM16.
629 switch (CodecSampleRate(rtp_header->header.payloadType)) {
631 rtp_header->header.payloadType = FLAGS_pcm16b;
634 rtp_header->header.payloadType = FLAGS_pcm16b_wb;
637 rtp_header->header.payloadType = FLAGS_pcm16b_swb32;
640 rtp_header->header.payloadType = FLAGS_pcm16b_swb48;
643 std::cerr << "Payload type " <<
644 static_cast<int>(rtp_header->header.payloadType) <<
645 " not supported or unknown." << std::endl;
646 webrtc::Trace::ReturnTrace();
653 int CodecSampleRate(uint8_t payload_type) {
654 if (payload_type == FLAGS_pcmu ||
655 payload_type == FLAGS_pcma ||
656 payload_type == FLAGS_ilbc ||
657 payload_type == FLAGS_pcm16b ||
658 payload_type == FLAGS_cn_nb) {
660 } else if (payload_type == FLAGS_isac ||
661 payload_type == FLAGS_pcm16b_wb ||
662 payload_type == FLAGS_g722 ||
663 payload_type == FLAGS_cn_wb) {
665 } else if (payload_type == FLAGS_isac_swb ||
666 payload_type == FLAGS_pcm16b_swb32 ||
667 payload_type == FLAGS_cn_swb32) {
669 } else if (payload_type == FLAGS_opus || payload_type == FLAGS_pcm16b_swb48 ||
670 payload_type == FLAGS_cn_swb48) {
672 } else if (payload_type == FLAGS_avt ||
673 payload_type == FLAGS_red) {
680 int CodecTimestampRate(uint8_t payload_type) {
681 if (payload_type == FLAGS_g722) {
684 return CodecSampleRate(payload_type);
688 bool IsComfortNosie(uint8_t payload_type) {
689 if (payload_type == FLAGS_cn_nb ||
690 payload_type == FLAGS_cn_wb ||
691 payload_type == FLAGS_cn_swb32 ||
692 payload_type == FLAGS_cn_swb48) {