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