1 /* 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 11 // TODO(hlundin): The functionality in this file should be moved into one or 12 // several classes. 13 14 #include <assert.h> 15 #include <stdio.h> 16 17 #include <algorithm> 18 #include <iostream> 19 #include <string> 20 21 #include "google/gflags.h" 22 #include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" 23 #include "webrtc/modules/audio_coding/neteq/interface/neteq.h" 24 #include "webrtc/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h" 25 #include "webrtc/modules/audio_coding/neteq/test/NETEQTEST_DummyRTPpacket.h" 26 #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" 27 #include "webrtc/modules/interface/module_common_types.h" 28 #include "webrtc/system_wrappers/interface/scoped_ptr.h" 29 #include "webrtc/system_wrappers/interface/trace.h" 30 #include "webrtc/test/testsupport/fileutils.h" 31 #include "webrtc/typedefs.h" 32 33 using webrtc::NetEq; 34 using webrtc::WebRtcRTPHeader; 35 36 // Flag validators. 37 static bool ValidatePayloadType(const char* flagname, int32_t value) { 38 if (value >= 0 && value <= 127) // Value is ok. 39 return true; 40 printf("Invalid value for --%s: %d\n", flagname, static_cast<int>(value)); 41 return false; 42 } 43 44 // Define command line flags. 45 DEFINE_int32(pcmu, 0, "RTP payload type for PCM-u"); 46 static const bool pcmu_dummy = 47 google::RegisterFlagValidator(&FLAGS_pcmu, &ValidatePayloadType); 48 DEFINE_int32(pcma, 8, "RTP payload type for PCM-a"); 49 static const bool pcma_dummy = 50 google::RegisterFlagValidator(&FLAGS_pcma, &ValidatePayloadType); 51 DEFINE_int32(ilbc, 102, "RTP payload type for iLBC"); 52 static const bool ilbc_dummy = 53 google::RegisterFlagValidator(&FLAGS_ilbc, &ValidatePayloadType); 54 DEFINE_int32(isac, 103, "RTP payload type for iSAC"); 55 static const bool isac_dummy = 56 google::RegisterFlagValidator(&FLAGS_isac, &ValidatePayloadType); 57 DEFINE_int32(isac_swb, 104, "RTP payload type for iSAC-swb (32 kHz)"); 58 static const bool isac_swb_dummy = 59 google::RegisterFlagValidator(&FLAGS_isac_swb, &ValidatePayloadType); 60 DEFINE_int32(pcm16b, 93, "RTP payload type for PCM16b-nb (8 kHz)"); 61 static const bool pcm16b_dummy = 62 google::RegisterFlagValidator(&FLAGS_pcm16b, &ValidatePayloadType); 63 DEFINE_int32(pcm16b_wb, 94, "RTP payload type for PCM16b-wb (16 kHz)"); 64 static const bool pcm16b_wb_dummy = 65 google::RegisterFlagValidator(&FLAGS_pcm16b_wb, &ValidatePayloadType); 66 DEFINE_int32(pcm16b_swb32, 95, "RTP payload type for PCM16b-swb32 (32 kHz)"); 67 static const bool pcm16b_swb32_dummy = 68 google::RegisterFlagValidator(&FLAGS_pcm16b_swb32, &ValidatePayloadType); 69 DEFINE_int32(pcm16b_swb48, 96, "RTP payload type for PCM16b-swb48 (48 kHz)"); 70 static const bool pcm16b_swb48_dummy = 71 google::RegisterFlagValidator(&FLAGS_pcm16b_swb48, &ValidatePayloadType); 72 DEFINE_int32(g722, 9, "RTP payload type for G.722"); 73 static const bool g722_dummy = 74 google::RegisterFlagValidator(&FLAGS_g722, &ValidatePayloadType); 75 DEFINE_int32(avt, 106, "RTP payload type for AVT/DTMF"); 76 static const bool avt_dummy = 77 google::RegisterFlagValidator(&FLAGS_avt, &ValidatePayloadType); 78 DEFINE_int32(red, 117, "RTP payload type for redundant audio (RED)"); 79 static const bool red_dummy = 80 google::RegisterFlagValidator(&FLAGS_red, &ValidatePayloadType); 81 DEFINE_int32(cn_nb, 13, "RTP payload type for comfort noise (8 kHz)"); 82 static const bool cn_nb_dummy = 83 google::RegisterFlagValidator(&FLAGS_cn_nb, &ValidatePayloadType); 84 DEFINE_int32(cn_wb, 98, "RTP payload type for comfort noise (16 kHz)"); 85 static const bool cn_wb_dummy = 86 google::RegisterFlagValidator(&FLAGS_cn_wb, &ValidatePayloadType); 87 DEFINE_int32(cn_swb32, 99, "RTP payload type for comfort noise (32 kHz)"); 88 static const bool cn_swb32_dummy = 89 google::RegisterFlagValidator(&FLAGS_cn_swb32, &ValidatePayloadType); 90 DEFINE_int32(cn_swb48, 100, "RTP payload type for comfort noise (48 kHz)"); 91 static const bool cn_swb48_dummy = 92 google::RegisterFlagValidator(&FLAGS_cn_swb48, &ValidatePayloadType); 93 DEFINE_bool(codec_map, false, "Prints the mapping between RTP payload type and " 94 "codec"); 95 DEFINE_bool(dummy_rtp, false, "The input file contains ""dummy"" RTP data, " 96 "i.e., only headers"); 97 DEFINE_string(replacement_audio_file, "", 98 "A PCM file that will be used to populate ""dummy"" RTP packets"); 99 100 // Declaring helper functions (defined further down in this file). 101 std::string CodecName(webrtc::NetEqDecoder codec); 102 void RegisterPayloadTypes(NetEq* neteq); 103 void PrintCodecMapping(); 104 size_t ReplacePayload(webrtc::test::InputAudioFile* replacement_audio_file, 105 webrtc::scoped_ptr<int16_t[]>* replacement_audio, 106 webrtc::scoped_ptr<uint8_t[]>* payload, 107 size_t* payload_mem_size_bytes, 108 size_t* frame_size_samples, 109 WebRtcRTPHeader* rtp_header, 110 NETEQTEST_RTPpacket* next_rtp); 111 int CodecSampleRate(uint8_t payload_type); 112 int CodecTimestampRate(uint8_t payload_type); 113 bool IsComfortNosie(uint8_t payload_type); 114 115 int main(int argc, char* argv[]) { 116 static const int kMaxChannels = 5; 117 static const int kMaxSamplesPerMs = 48000 / 1000; 118 static const int kOutputBlockSizeMs = 10; 119 120 std::string program_name = argv[0]; 121 std::string usage = "Tool for decoding an RTP dump file using NetEq.\n" 122 "Run " + program_name + " --helpshort for usage.\n" 123 "Example usage:\n" + program_name + 124 " input.rtp output.pcm\n"; 125 google::SetUsageMessage(usage); 126 google::ParseCommandLineFlags(&argc, &argv, true); 127 128 if (FLAGS_codec_map) { 129 PrintCodecMapping(); 130 } 131 132 if (argc != 3) { 133 if (FLAGS_codec_map) { 134 // We have already printed the codec map. Just end the program. 135 return 0; 136 } 137 // Print usage information. 138 std::cout << google::ProgramUsage(); 139 return 0; 140 } 141 142 FILE* in_file = fopen(argv[1], "rb"); 143 if (!in_file) { 144 std::cerr << "Cannot open input file " << argv[1] << std::endl; 145 exit(1); 146 } 147 std::cout << "Input file: " << argv[1] << std::endl; 148 149 FILE* out_file = fopen(argv[2], "wb"); 150 if (!in_file) { 151 std::cerr << "Cannot open output file " << argv[2] << std::endl; 152 exit(1); 153 } 154 std::cout << "Output file: " << argv[2] << std::endl; 155 156 // Check if a replacement audio file was provided, and if so, open it. 157 bool replace_payload = false; 158 webrtc::scoped_ptr<webrtc::test::InputAudioFile> replacement_audio_file; 159 if (!FLAGS_replacement_audio_file.empty()) { 160 replacement_audio_file.reset( 161 new webrtc::test::InputAudioFile(FLAGS_replacement_audio_file)); 162 replace_payload = true; 163 } 164 165 // Read RTP file header. 166 if (NETEQTEST_RTPpacket::skipFileHeader(in_file) != 0) { 167 std::cerr << "Wrong format in RTP file" << std::endl; 168 exit(1); 169 } 170 171 // Enable tracing. 172 webrtc::Trace::CreateTrace(); 173 webrtc::Trace::SetTraceFile((webrtc::test::OutputPath() + 174 "neteq_trace.txt").c_str()); 175 webrtc::Trace::set_level_filter(webrtc::kTraceAll); 176 177 // Initialize NetEq instance. 178 int sample_rate_hz = 16000; 179 NetEq::Config config; 180 config.sample_rate_hz = sample_rate_hz; 181 NetEq* neteq = NetEq::Create(config); 182 RegisterPayloadTypes(neteq); 183 184 // Read first packet. 185 NETEQTEST_RTPpacket* rtp; 186 NETEQTEST_RTPpacket* next_rtp = NULL; 187 if (!FLAGS_dummy_rtp) { 188 rtp = new NETEQTEST_RTPpacket(); 189 if (replace_payload) { 190 next_rtp = new NETEQTEST_RTPpacket(); 191 } 192 } else { 193 rtp = new NETEQTEST_DummyRTPpacket(); 194 if (replace_payload) { 195 next_rtp = new NETEQTEST_DummyRTPpacket(); 196 } 197 } 198 rtp->readFromFile(in_file); 199 if (rtp->dataLen() < 0) { 200 std::cout << "Warning: RTP file is empty" << std::endl; 201 } 202 203 // Set up variables for audio replacement if needed. 204 size_t input_frame_size_timestamps = 0; 205 webrtc::scoped_ptr<int16_t[]> replacement_audio; 206 webrtc::scoped_ptr<uint8_t[]> payload; 207 size_t payload_mem_size_bytes = 0; 208 if (replace_payload) { 209 // Initially assume that the frame size is 30 ms at the initial sample rate. 210 // This value will be replaced with the correct one as soon as two 211 // consecutive packets are found. 212 input_frame_size_timestamps = 30 * sample_rate_hz / 1000; 213 replacement_audio.reset(new int16_t[input_frame_size_timestamps]); 214 payload_mem_size_bytes = 2 * input_frame_size_timestamps; 215 payload.reset(new uint8_t[payload_mem_size_bytes]); 216 assert(next_rtp); 217 next_rtp->readFromFile(in_file); 218 } 219 220 // This is the main simulation loop. 221 int time_now_ms = rtp->time(); // Start immediately with the first packet. 222 int next_input_time_ms = rtp->time(); 223 int next_output_time_ms = time_now_ms; 224 if (time_now_ms % kOutputBlockSizeMs != 0) { 225 // Make sure that next_output_time_ms is rounded up to the next multiple 226 // of kOutputBlockSizeMs. (Legacy bit-exactness.) 227 next_output_time_ms += 228 kOutputBlockSizeMs - time_now_ms % kOutputBlockSizeMs; 229 } 230 while (rtp->dataLen() >= 0) { 231 // Check if it is time to insert packet. 232 while (time_now_ms >= next_input_time_ms && rtp->dataLen() >= 0) { 233 if (rtp->dataLen() > 0) { 234 // Parse RTP header. 235 WebRtcRTPHeader rtp_header; 236 rtp->parseHeader(&rtp_header); 237 uint8_t* payload_ptr = rtp->payload(); 238 size_t payload_len = rtp->payloadLen(); 239 if (replace_payload) { 240 payload_len = ReplacePayload(replacement_audio_file.get(), 241 &replacement_audio, 242 &payload, 243 &payload_mem_size_bytes, 244 &input_frame_size_timestamps, 245 &rtp_header, 246 next_rtp); 247 payload_ptr = payload.get(); 248 } 249 int error = neteq->InsertPacket(rtp_header, payload_ptr, 250 static_cast<int>(payload_len), 251 rtp->time() * sample_rate_hz / 1000); 252 if (error != NetEq::kOK) { 253 std::cerr << "InsertPacket returned error code " << 254 neteq->LastError() << std::endl; 255 } 256 } 257 // Get next packet from file. 258 rtp->readFromFile(in_file); 259 if (replace_payload) { 260 // At this point |rtp| contains the packet *after* |next_rtp|. 261 // Swap RTP packet objects between |rtp| and |next_rtp|. 262 NETEQTEST_RTPpacket* temp_rtp = rtp; 263 rtp = next_rtp; 264 next_rtp = temp_rtp; 265 } 266 next_input_time_ms = rtp->time(); 267 } 268 269 // Check if it is time to get output audio. 270 if (time_now_ms >= next_output_time_ms) { 271 static const int kOutDataLen = kOutputBlockSizeMs * kMaxSamplesPerMs * 272 kMaxChannels; 273 int16_t out_data[kOutDataLen]; 274 int num_channels; 275 int samples_per_channel; 276 int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel, 277 &num_channels, NULL); 278 if (error != NetEq::kOK) { 279 std::cerr << "GetAudio returned error code " << 280 neteq->LastError() << std::endl; 281 } else { 282 // Calculate sample rate from output size. 283 sample_rate_hz = 1000 * samples_per_channel / kOutputBlockSizeMs; 284 } 285 286 // Write to file. 287 // TODO(hlundin): Make writing to file optional. 288 size_t write_len = samples_per_channel * num_channels; 289 if (fwrite(out_data, sizeof(out_data[0]), write_len, out_file) != 290 write_len) { 291 std::cerr << "Error while writing to file" << std::endl; 292 webrtc::Trace::ReturnTrace(); 293 exit(1); 294 } 295 next_output_time_ms += kOutputBlockSizeMs; 296 } 297 // Advance time to next event. 298 time_now_ms = std::min(next_input_time_ms, next_output_time_ms); 299 } 300 301 std::cout << "Simulation done" << std::endl; 302 303 fclose(in_file); 304 fclose(out_file); 305 delete rtp; 306 delete next_rtp; 307 delete neteq; 308 webrtc::Trace::ReturnTrace(); 309 return 0; 310 } 311 312 313 // Help functions. 314 315 // Maps a codec type to a printable name string. 316 std::string CodecName(webrtc::NetEqDecoder codec) { 317 switch (codec) { 318 case webrtc::kDecoderPCMu: 319 return "PCM-u"; 320 case webrtc::kDecoderPCMa: 321 return "PCM-a"; 322 case webrtc::kDecoderILBC: 323 return "iLBC"; 324 case webrtc::kDecoderISAC: 325 return "iSAC"; 326 case webrtc::kDecoderISACswb: 327 return "iSAC-swb (32 kHz)"; 328 case webrtc::kDecoderPCM16B: 329 return "PCM16b-nb (8 kHz)"; 330 case webrtc::kDecoderPCM16Bwb: 331 return "PCM16b-wb (16 kHz)"; 332 case webrtc::kDecoderPCM16Bswb32kHz: 333 return "PCM16b-swb32 (32 kHz)"; 334 case webrtc::kDecoderPCM16Bswb48kHz: 335 return "PCM16b-swb48 (48 kHz)"; 336 case webrtc::kDecoderG722: 337 return "G.722"; 338 case webrtc::kDecoderRED: 339 return "redundant audio (RED)"; 340 case webrtc::kDecoderAVT: 341 return "AVT/DTMF"; 342 case webrtc::kDecoderCNGnb: 343 return "comfort noise (8 kHz)"; 344 case webrtc::kDecoderCNGwb: 345 return "comfort noise (16 kHz)"; 346 case webrtc::kDecoderCNGswb32kHz: 347 return "comfort noise (32 kHz)"; 348 case webrtc::kDecoderCNGswb48kHz: 349 return "comfort noise (48 kHz)"; 350 default: 351 assert(false); 352 return "undefined"; 353 } 354 } 355 356 // Registers all decoders in |neteq|. 357 void RegisterPayloadTypes(NetEq* neteq) { 358 assert(neteq); 359 int error; 360 error = neteq->RegisterPayloadType(webrtc::kDecoderPCMu, FLAGS_pcmu); 361 if (error) { 362 std::cerr << "Cannot register payload type " << FLAGS_pcmu << 363 " as " << CodecName(webrtc::kDecoderPCMu).c_str() << std::endl; 364 exit(1); 365 } 366 error = neteq->RegisterPayloadType(webrtc::kDecoderPCMa, FLAGS_pcma); 367 if (error) { 368 std::cerr << "Cannot register payload type " << FLAGS_pcma << 369 " as " << CodecName(webrtc::kDecoderPCMa).c_str() << std::endl; 370 exit(1); 371 } 372 error = neteq->RegisterPayloadType(webrtc::kDecoderILBC, FLAGS_ilbc); 373 if (error) { 374 std::cerr << "Cannot register payload type " << FLAGS_ilbc << 375 " as " << CodecName(webrtc::kDecoderILBC).c_str() << std::endl; 376 exit(1); 377 } 378 error = neteq->RegisterPayloadType(webrtc::kDecoderISAC, FLAGS_isac); 379 if (error) { 380 std::cerr << "Cannot register payload type " << FLAGS_isac << 381 " as " << CodecName(webrtc::kDecoderISAC).c_str() << std::endl; 382 exit(1); 383 } 384 error = neteq->RegisterPayloadType(webrtc::kDecoderISACswb, FLAGS_isac_swb); 385 if (error) { 386 std::cerr << "Cannot register payload type " << FLAGS_isac_swb << 387 " as " << CodecName(webrtc::kDecoderISACswb).c_str() << std::endl; 388 exit(1); 389 } 390 error = neteq->RegisterPayloadType(webrtc::kDecoderPCM16B, FLAGS_pcm16b); 391 if (error) { 392 std::cerr << "Cannot register payload type " << FLAGS_pcm16b << 393 " as " << CodecName(webrtc::kDecoderPCM16B).c_str() << std::endl; 394 exit(1); 395 } 396 error = neteq->RegisterPayloadType(webrtc::kDecoderPCM16Bwb, 397 FLAGS_pcm16b_wb); 398 if (error) { 399 std::cerr << "Cannot register payload type " << FLAGS_pcm16b_wb << 400 " as " << CodecName(webrtc::kDecoderPCM16Bwb).c_str() << std::endl; 401 exit(1); 402 } 403 error = neteq->RegisterPayloadType(webrtc::kDecoderPCM16Bswb32kHz, 404 FLAGS_pcm16b_swb32); 405 if (error) { 406 std::cerr << "Cannot register payload type " << FLAGS_pcm16b_swb32 << 407 " as " << CodecName(webrtc::kDecoderPCM16Bswb32kHz).c_str() << 408 std::endl; 409 exit(1); 410 } 411 error = neteq->RegisterPayloadType(webrtc::kDecoderPCM16Bswb48kHz, 412 FLAGS_pcm16b_swb48); 413 if (error) { 414 std::cerr << "Cannot register payload type " << FLAGS_pcm16b_swb48 << 415 " as " << CodecName(webrtc::kDecoderPCM16Bswb48kHz).c_str() << 416 std::endl; 417 exit(1); 418 } 419 error = neteq->RegisterPayloadType(webrtc::kDecoderG722, FLAGS_g722); 420 if (error) { 421 std::cerr << "Cannot register payload type " << FLAGS_g722 << 422 " as " << CodecName(webrtc::kDecoderG722).c_str() << std::endl; 423 exit(1); 424 } 425 error = neteq->RegisterPayloadType(webrtc::kDecoderAVT, FLAGS_avt); 426 if (error) { 427 std::cerr << "Cannot register payload type " << FLAGS_avt << 428 " as " << CodecName(webrtc::kDecoderAVT).c_str() << std::endl; 429 exit(1); 430 } 431 error = neteq->RegisterPayloadType(webrtc::kDecoderRED, FLAGS_red); 432 if (error) { 433 std::cerr << "Cannot register payload type " << FLAGS_red << 434 " as " << CodecName(webrtc::kDecoderRED).c_str() << std::endl; 435 exit(1); 436 } 437 error = neteq->RegisterPayloadType(webrtc::kDecoderCNGnb, FLAGS_cn_nb); 438 if (error) { 439 std::cerr << "Cannot register payload type " << FLAGS_cn_nb << 440 " as " << CodecName(webrtc::kDecoderCNGnb).c_str() << std::endl; 441 exit(1); 442 } 443 error = neteq->RegisterPayloadType(webrtc::kDecoderCNGwb, FLAGS_cn_wb); 444 if (error) { 445 std::cerr << "Cannot register payload type " << FLAGS_cn_wb << 446 " as " << CodecName(webrtc::kDecoderCNGwb).c_str() << std::endl; 447 exit(1); 448 } 449 error = neteq->RegisterPayloadType(webrtc::kDecoderCNGswb32kHz, 450 FLAGS_cn_swb32); 451 if (error) { 452 std::cerr << "Cannot register payload type " << FLAGS_cn_swb32 << 453 " as " << CodecName(webrtc::kDecoderCNGswb32kHz).c_str() << std::endl; 454 exit(1); 455 } 456 error = neteq->RegisterPayloadType(webrtc::kDecoderCNGswb48kHz, 457 FLAGS_cn_swb48); 458 if (error) { 459 std::cerr << "Cannot register payload type " << FLAGS_cn_swb48 << 460 " as " << CodecName(webrtc::kDecoderCNGswb48kHz).c_str() << std::endl; 461 exit(1); 462 } 463 } 464 465 void PrintCodecMapping() { 466 std::cout << CodecName(webrtc::kDecoderPCMu).c_str() << ": " << FLAGS_pcmu << 467 std::endl; 468 std::cout << CodecName(webrtc::kDecoderPCMa).c_str() << ": " << FLAGS_pcma << 469 std::endl; 470 std::cout << CodecName(webrtc::kDecoderILBC).c_str() << ": " << FLAGS_ilbc << 471 std::endl; 472 std::cout << CodecName(webrtc::kDecoderISAC).c_str() << ": " << FLAGS_isac << 473 std::endl; 474 std::cout << CodecName(webrtc::kDecoderISACswb).c_str() << ": " << 475 FLAGS_isac_swb << std::endl; 476 std::cout << CodecName(webrtc::kDecoderPCM16B).c_str() << ": " << 477 FLAGS_pcm16b << std::endl; 478 std::cout << CodecName(webrtc::kDecoderPCM16Bwb).c_str() << ": " << 479 FLAGS_pcm16b_wb << std::endl; 480 std::cout << CodecName(webrtc::kDecoderPCM16Bswb32kHz).c_str() << ": " << 481 FLAGS_pcm16b_swb32 << std::endl; 482 std::cout << CodecName(webrtc::kDecoderPCM16Bswb48kHz).c_str() << ": " << 483 FLAGS_pcm16b_swb48 << std::endl; 484 std::cout << CodecName(webrtc::kDecoderG722).c_str() << ": " << FLAGS_g722 << 485 std::endl; 486 std::cout << CodecName(webrtc::kDecoderAVT).c_str() << ": " << FLAGS_avt << 487 std::endl; 488 std::cout << CodecName(webrtc::kDecoderRED).c_str() << ": " << FLAGS_red << 489 std::endl; 490 std::cout << CodecName(webrtc::kDecoderCNGnb).c_str() << ": " << 491 FLAGS_cn_nb << std::endl; 492 std::cout << CodecName(webrtc::kDecoderCNGwb).c_str() << ": " << 493 FLAGS_cn_wb << std::endl; 494 std::cout << CodecName(webrtc::kDecoderCNGswb32kHz).c_str() << ": " << 495 FLAGS_cn_swb32 << std::endl; 496 std::cout << CodecName(webrtc::kDecoderCNGswb48kHz).c_str() << ": " << 497 FLAGS_cn_swb48 << std::endl; 498 } 499 500 size_t ReplacePayload(webrtc::test::InputAudioFile* replacement_audio_file, 501 webrtc::scoped_ptr<int16_t[]>* replacement_audio, 502 webrtc::scoped_ptr<uint8_t[]>* payload, 503 size_t* payload_mem_size_bytes, 504 size_t* frame_size_samples, 505 WebRtcRTPHeader* rtp_header, 506 NETEQTEST_RTPpacket* next_rtp) { 507 size_t payload_len = 0; 508 // Check for CNG. 509 if (IsComfortNosie(rtp_header->header.payloadType)) { 510 // If CNG, simply insert a zero-energy one-byte payload. 511 if (*payload_mem_size_bytes < 1) { 512 (*payload).reset(new uint8_t[1]); 513 *payload_mem_size_bytes = 1; 514 } 515 (*payload)[0] = 127; // Max attenuation of CNG. 516 payload_len = 1; 517 } else { 518 if (next_rtp->payloadLen() > 0) { 519 // Check if payload length has changed. 520 if (next_rtp->sequenceNumber() == rtp_header->header.sequenceNumber + 1) { 521 if (*frame_size_samples != 522 next_rtp->timeStamp() - rtp_header->header.timestamp) { 523 *frame_size_samples = 524 next_rtp->timeStamp() - rtp_header->header.timestamp; 525 (*replacement_audio).reset( 526 new int16_t[*frame_size_samples]); 527 *payload_mem_size_bytes = 2 * *frame_size_samples; 528 (*payload).reset(new uint8_t[*payload_mem_size_bytes]); 529 } 530 } 531 } 532 // Get new speech. 533 assert((*replacement_audio).get()); 534 if (CodecTimestampRate(rtp_header->header.payloadType) != 535 CodecSampleRate(rtp_header->header.payloadType) || 536 rtp_header->header.payloadType == FLAGS_red || 537 rtp_header->header.payloadType == FLAGS_avt) { 538 // Some codecs have different sample and timestamp rates. And neither 539 // RED nor DTMF is supported for replacement. 540 std::cerr << "Codec not supported for audio replacement." << 541 std::endl; 542 webrtc::Trace::ReturnTrace(); 543 exit(1); 544 } 545 assert(*frame_size_samples > 0); 546 if (!replacement_audio_file->Read(*frame_size_samples, 547 (*replacement_audio).get())) { 548 std::cerr << "Could no read replacement audio file." << std::endl; 549 webrtc::Trace::ReturnTrace(); 550 exit(1); 551 } 552 // Encode it as PCM16. 553 assert((*payload).get()); 554 payload_len = WebRtcPcm16b_Encode((*replacement_audio).get(), 555 static_cast<int16_t>(*frame_size_samples), 556 (*payload).get()); 557 assert(payload_len == 2 * *frame_size_samples); 558 // Change payload type to PCM16. 559 switch (CodecSampleRate(rtp_header->header.payloadType)) { 560 case 8000: 561 rtp_header->header.payloadType = FLAGS_pcm16b; 562 break; 563 case 16000: 564 rtp_header->header.payloadType = FLAGS_pcm16b_wb; 565 break; 566 case 32000: 567 rtp_header->header.payloadType = FLAGS_pcm16b_swb32; 568 break; 569 case 48000: 570 rtp_header->header.payloadType = FLAGS_pcm16b_swb48; 571 break; 572 default: 573 std::cerr << "Payload type " << 574 static_cast<int>(rtp_header->header.payloadType) << 575 " not supported or unknown." << std::endl; 576 webrtc::Trace::ReturnTrace(); 577 exit(1); 578 assert(false); 579 } 580 } 581 return payload_len; 582 } 583 584 int CodecSampleRate(uint8_t payload_type) { 585 if (payload_type == FLAGS_pcmu || 586 payload_type == FLAGS_pcma || 587 payload_type == FLAGS_ilbc || 588 payload_type == FLAGS_pcm16b || 589 payload_type == FLAGS_cn_nb) { 590 return 8000; 591 } else if (payload_type == FLAGS_isac || 592 payload_type == FLAGS_pcm16b_wb || 593 payload_type == FLAGS_g722 || 594 payload_type == FLAGS_cn_wb) { 595 return 16000; 596 } else if (payload_type == FLAGS_isac_swb || 597 payload_type == FLAGS_pcm16b_swb32 || 598 payload_type == FLAGS_cn_swb32) { 599 return 32000; 600 } else if (payload_type == FLAGS_pcm16b_swb48 || 601 payload_type == FLAGS_cn_swb48) { 602 return 48000; 603 } else if (payload_type == FLAGS_avt || 604 payload_type == FLAGS_red) { 605 return 0; 606 } else { 607 return -1; 608 } 609 } 610 611 int CodecTimestampRate(uint8_t payload_type) { 612 if (payload_type == FLAGS_g722) { 613 return 8000; 614 } else { 615 return CodecSampleRate(payload_type); 616 } 617 } 618 619 bool IsComfortNosie(uint8_t payload_type) { 620 if (payload_type == FLAGS_cn_nb || 621 payload_type == FLAGS_cn_wb || 622 payload_type == FLAGS_cn_swb32 || 623 payload_type == FLAGS_cn_swb48) { 624 return true; 625 } else { 626 return false; 627 } 628 } 629