diff options
Diffstat (limited to 'chromium/third_party/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc')
-rw-r--r-- | chromium/third_party/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc | 628 |
1 files changed, 628 insertions, 0 deletions
diff --git a/chromium/third_party/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc b/chromium/third_party/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc new file mode 100644 index 00000000000..3c5f6b0bbaa --- /dev/null +++ b/chromium/third_party/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc @@ -0,0 +1,628 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// TODO(hlundin): The functionality in this file should be moved into one or +// several classes. + +#include <assert.h> +#include <stdio.h> + +#include <algorithm> +#include <iostream> +#include <string> + +#include "google/gflags.h" +#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" +#include "webrtc/modules/audio_coding/neteq/interface/neteq.h" +#include "webrtc/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h" +#include "webrtc/modules/audio_coding/neteq/test/NETEQTEST_DummyRTPpacket.h" +#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" +#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/system_wrappers/interface/trace.h" +#include "webrtc/test/testsupport/fileutils.h" +#include "webrtc/typedefs.h" + +using webrtc::NetEq; +using webrtc::WebRtcRTPHeader; + +// Flag validators. +static bool ValidatePayloadType(const char* flagname, int32_t value) { + if (value >= 0 && value <= 127) // Value is ok. + return true; + printf("Invalid value for --%s: %d\n", flagname, static_cast<int>(value)); + return false; +} + +// Define command line flags. +DEFINE_int32(pcmu, 0, "RTP payload type for PCM-u"); +static const bool pcmu_dummy = + google::RegisterFlagValidator(&FLAGS_pcmu, &ValidatePayloadType); +DEFINE_int32(pcma, 8, "RTP payload type for PCM-a"); +static const bool pcma_dummy = + google::RegisterFlagValidator(&FLAGS_pcma, &ValidatePayloadType); +DEFINE_int32(ilbc, 102, "RTP payload type for iLBC"); +static const bool ilbc_dummy = + google::RegisterFlagValidator(&FLAGS_ilbc, &ValidatePayloadType); +DEFINE_int32(isac, 103, "RTP payload type for iSAC"); +static const bool isac_dummy = + google::RegisterFlagValidator(&FLAGS_isac, &ValidatePayloadType); +DEFINE_int32(isac_swb, 104, "RTP payload type for iSAC-swb (32 kHz)"); +static const bool isac_swb_dummy = + google::RegisterFlagValidator(&FLAGS_isac_swb, &ValidatePayloadType); +DEFINE_int32(pcm16b, 93, "RTP payload type for PCM16b-nb (8 kHz)"); +static const bool pcm16b_dummy = + google::RegisterFlagValidator(&FLAGS_pcm16b, &ValidatePayloadType); +DEFINE_int32(pcm16b_wb, 94, "RTP payload type for PCM16b-wb (16 kHz)"); +static const bool pcm16b_wb_dummy = + google::RegisterFlagValidator(&FLAGS_pcm16b_wb, &ValidatePayloadType); +DEFINE_int32(pcm16b_swb32, 95, "RTP payload type for PCM16b-swb32 (32 kHz)"); +static const bool pcm16b_swb32_dummy = + google::RegisterFlagValidator(&FLAGS_pcm16b_swb32, &ValidatePayloadType); +DEFINE_int32(pcm16b_swb48, 96, "RTP payload type for PCM16b-swb48 (48 kHz)"); +static const bool pcm16b_swb48_dummy = + google::RegisterFlagValidator(&FLAGS_pcm16b_swb48, &ValidatePayloadType); +DEFINE_int32(g722, 9, "RTP payload type for G.722"); +static const bool g722_dummy = + google::RegisterFlagValidator(&FLAGS_g722, &ValidatePayloadType); +DEFINE_int32(avt, 106, "RTP payload type for AVT/DTMF"); +static const bool avt_dummy = + google::RegisterFlagValidator(&FLAGS_avt, &ValidatePayloadType); +DEFINE_int32(red, 117, "RTP payload type for redundant audio (RED)"); +static const bool red_dummy = + google::RegisterFlagValidator(&FLAGS_red, &ValidatePayloadType); +DEFINE_int32(cn_nb, 13, "RTP payload type for comfort noise (8 kHz)"); +static const bool cn_nb_dummy = + google::RegisterFlagValidator(&FLAGS_cn_nb, &ValidatePayloadType); +DEFINE_int32(cn_wb, 98, "RTP payload type for comfort noise (16 kHz)"); +static const bool cn_wb_dummy = + google::RegisterFlagValidator(&FLAGS_cn_wb, &ValidatePayloadType); +DEFINE_int32(cn_swb32, 99, "RTP payload type for comfort noise (32 kHz)"); +static const bool cn_swb32_dummy = + google::RegisterFlagValidator(&FLAGS_cn_swb32, &ValidatePayloadType); +DEFINE_int32(cn_swb48, 100, "RTP payload type for comfort noise (48 kHz)"); +static const bool cn_swb48_dummy = + google::RegisterFlagValidator(&FLAGS_cn_swb48, &ValidatePayloadType); +DEFINE_bool(codec_map, false, "Prints the mapping between RTP payload type and " + "codec"); +DEFINE_bool(dummy_rtp, false, "The input file contains ""dummy"" RTP data, " + "i.e., only headers"); +DEFINE_string(replacement_audio_file, "", + "A PCM file that will be used to populate ""dummy"" RTP packets"); + +// Declaring helper functions (defined further down in this file). +std::string CodecName(webrtc::NetEqDecoder codec); +void RegisterPayloadTypes(NetEq* neteq); +void PrintCodecMapping(); +size_t ReplacePayload(webrtc::test::InputAudioFile* replacement_audio_file, + webrtc::scoped_ptr<int16_t[]>* replacement_audio, + webrtc::scoped_ptr<uint8_t[]>* payload, + size_t* payload_mem_size_bytes, + size_t* frame_size_samples, + WebRtcRTPHeader* rtp_header, + NETEQTEST_RTPpacket* next_rtp); +int CodecSampleRate(uint8_t payload_type); +int CodecTimestampRate(uint8_t payload_type); +bool IsComfortNosie(uint8_t payload_type); + +int main(int argc, char* argv[]) { + static const int kMaxChannels = 5; + static const int kMaxSamplesPerMs = 48000 / 1000; + static const int kOutputBlockSizeMs = 10; + + std::string program_name = argv[0]; + std::string usage = "Tool for decoding an RTP dump file using NetEq.\n" + "Run " + program_name + " --helpshort for usage.\n" + "Example usage:\n" + program_name + + " input.rtp output.pcm\n"; + google::SetUsageMessage(usage); + google::ParseCommandLineFlags(&argc, &argv, true); + + if (FLAGS_codec_map) { + PrintCodecMapping(); + } + + if (argc != 3) { + if (FLAGS_codec_map) { + // We have already printed the codec map. Just end the program. + return 0; + } + // Print usage information. + std::cout << google::ProgramUsage(); + return 0; + } + + FILE* in_file = fopen(argv[1], "rb"); + if (!in_file) { + std::cerr << "Cannot open input file " << argv[1] << std::endl; + exit(1); + } + std::cout << "Input file: " << argv[1] << std::endl; + + FILE* out_file = fopen(argv[2], "wb"); + if (!in_file) { + std::cerr << "Cannot open output file " << argv[2] << std::endl; + exit(1); + } + std::cout << "Output file: " << argv[2] << std::endl; + + // Check if a replacement audio file was provided, and if so, open it. + bool replace_payload = false; + webrtc::scoped_ptr<webrtc::test::InputAudioFile> replacement_audio_file; + if (!FLAGS_replacement_audio_file.empty()) { + replacement_audio_file.reset( + new webrtc::test::InputAudioFile(FLAGS_replacement_audio_file)); + replace_payload = true; + } + + // Read RTP file header. + if (NETEQTEST_RTPpacket::skipFileHeader(in_file) != 0) { + std::cerr << "Wrong format in RTP file" << std::endl; + exit(1); + } + + // Enable tracing. + webrtc::Trace::CreateTrace(); + webrtc::Trace::SetTraceFile((webrtc::test::OutputPath() + + "neteq_trace.txt").c_str()); + webrtc::Trace::set_level_filter(webrtc::kTraceAll); + + // Initialize NetEq instance. + int sample_rate_hz = 16000; + NetEq::Config config; + config.sample_rate_hz = sample_rate_hz; + NetEq* neteq = NetEq::Create(config); + RegisterPayloadTypes(neteq); + + // Read first packet. + NETEQTEST_RTPpacket* rtp; + NETEQTEST_RTPpacket* next_rtp = NULL; + if (!FLAGS_dummy_rtp) { + rtp = new NETEQTEST_RTPpacket(); + if (replace_payload) { + next_rtp = new NETEQTEST_RTPpacket(); + } + } else { + rtp = new NETEQTEST_DummyRTPpacket(); + if (replace_payload) { + next_rtp = new NETEQTEST_DummyRTPpacket(); + } + } + rtp->readFromFile(in_file); + if (rtp->dataLen() < 0) { + std::cout << "Warning: RTP file is empty" << std::endl; + } + + // Set up variables for audio replacement if needed. + size_t input_frame_size_timestamps = 0; + webrtc::scoped_ptr<int16_t[]> replacement_audio; + webrtc::scoped_ptr<uint8_t[]> payload; + size_t payload_mem_size_bytes = 0; + if (replace_payload) { + // Initially assume that the frame size is 30 ms at the initial sample rate. + // This value will be replaced with the correct one as soon as two + // consecutive packets are found. + input_frame_size_timestamps = 30 * sample_rate_hz / 1000; + replacement_audio.reset(new int16_t[input_frame_size_timestamps]); + payload_mem_size_bytes = 2 * input_frame_size_timestamps; + payload.reset(new uint8_t[payload_mem_size_bytes]); + assert(next_rtp); + next_rtp->readFromFile(in_file); + } + + // This is the main simulation loop. + int time_now_ms = rtp->time(); // Start immediately with the first packet. + int next_input_time_ms = rtp->time(); + int next_output_time_ms = time_now_ms; + if (time_now_ms % kOutputBlockSizeMs != 0) { + // Make sure that next_output_time_ms is rounded up to the next multiple + // of kOutputBlockSizeMs. (Legacy bit-exactness.) + next_output_time_ms += + kOutputBlockSizeMs - time_now_ms % kOutputBlockSizeMs; + } + while (rtp->dataLen() >= 0) { + // Check if it is time to insert packet. + while (time_now_ms >= next_input_time_ms && rtp->dataLen() >= 0) { + if (rtp->dataLen() > 0) { + // Parse RTP header. + WebRtcRTPHeader rtp_header; + rtp->parseHeader(&rtp_header); + uint8_t* payload_ptr = rtp->payload(); + size_t payload_len = rtp->payloadLen(); + if (replace_payload) { + payload_len = ReplacePayload(replacement_audio_file.get(), + &replacement_audio, + &payload, + &payload_mem_size_bytes, + &input_frame_size_timestamps, + &rtp_header, + next_rtp); + payload_ptr = payload.get(); + } + int error = neteq->InsertPacket(rtp_header, payload_ptr, + static_cast<int>(payload_len), + rtp->time() * sample_rate_hz / 1000); + if (error != NetEq::kOK) { + std::cerr << "InsertPacket returned error code " << + neteq->LastError() << std::endl; + } + } + // Get next packet from file. + rtp->readFromFile(in_file); + if (replace_payload) { + // At this point |rtp| contains the packet *after* |next_rtp|. + // Swap RTP packet objects between |rtp| and |next_rtp|. + NETEQTEST_RTPpacket* temp_rtp = rtp; + rtp = next_rtp; + next_rtp = temp_rtp; + } + next_input_time_ms = rtp->time(); + } + + // Check if it is time to get output audio. + if (time_now_ms >= next_output_time_ms) { + static const int kOutDataLen = kOutputBlockSizeMs * kMaxSamplesPerMs * + kMaxChannels; + int16_t out_data[kOutDataLen]; + int num_channels; + int samples_per_channel; + int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel, + &num_channels, NULL); + if (error != NetEq::kOK) { + std::cerr << "GetAudio returned error code " << + neteq->LastError() << std::endl; + } else { + // Calculate sample rate from output size. + sample_rate_hz = 1000 * samples_per_channel / kOutputBlockSizeMs; + } + + // Write to file. + // TODO(hlundin): Make writing to file optional. + size_t write_len = samples_per_channel * num_channels; + if (fwrite(out_data, sizeof(out_data[0]), write_len, out_file) != + write_len) { + std::cerr << "Error while writing to file" << std::endl; + webrtc::Trace::ReturnTrace(); + exit(1); + } + next_output_time_ms += kOutputBlockSizeMs; + } + // Advance time to next event. + time_now_ms = std::min(next_input_time_ms, next_output_time_ms); + } + + std::cout << "Simulation done" << std::endl; + + fclose(in_file); + fclose(out_file); + delete rtp; + delete next_rtp; + delete neteq; + webrtc::Trace::ReturnTrace(); + return 0; +} + + +// Help functions. + +// Maps a codec type to a printable name string. +std::string CodecName(webrtc::NetEqDecoder codec) { + switch (codec) { + case webrtc::kDecoderPCMu: + return "PCM-u"; + case webrtc::kDecoderPCMa: + return "PCM-a"; + case webrtc::kDecoderILBC: + return "iLBC"; + case webrtc::kDecoderISAC: + return "iSAC"; + case webrtc::kDecoderISACswb: + return "iSAC-swb (32 kHz)"; + case webrtc::kDecoderPCM16B: + return "PCM16b-nb (8 kHz)"; + case webrtc::kDecoderPCM16Bwb: + return "PCM16b-wb (16 kHz)"; + case webrtc::kDecoderPCM16Bswb32kHz: + return "PCM16b-swb32 (32 kHz)"; + case webrtc::kDecoderPCM16Bswb48kHz: + return "PCM16b-swb48 (48 kHz)"; + case webrtc::kDecoderG722: + return "G.722"; + case webrtc::kDecoderRED: + return "redundant audio (RED)"; + case webrtc::kDecoderAVT: + return "AVT/DTMF"; + case webrtc::kDecoderCNGnb: + return "comfort noise (8 kHz)"; + case webrtc::kDecoderCNGwb: + return "comfort noise (16 kHz)"; + case webrtc::kDecoderCNGswb32kHz: + return "comfort noise (32 kHz)"; + case webrtc::kDecoderCNGswb48kHz: + return "comfort noise (48 kHz)"; + default: + assert(false); + return "undefined"; + } +} + +// Registers all decoders in |neteq|. +void RegisterPayloadTypes(NetEq* neteq) { + assert(neteq); + int error; + error = neteq->RegisterPayloadType(webrtc::kDecoderPCMu, FLAGS_pcmu); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_pcmu << + " as " << CodecName(webrtc::kDecoderPCMu).c_str() << std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderPCMa, FLAGS_pcma); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_pcma << + " as " << CodecName(webrtc::kDecoderPCMa).c_str() << std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderILBC, FLAGS_ilbc); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_ilbc << + " as " << CodecName(webrtc::kDecoderILBC).c_str() << std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderISAC, FLAGS_isac); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_isac << + " as " << CodecName(webrtc::kDecoderISAC).c_str() << std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderISACswb, FLAGS_isac_swb); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_isac_swb << + " as " << CodecName(webrtc::kDecoderISACswb).c_str() << std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderPCM16B, FLAGS_pcm16b); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_pcm16b << + " as " << CodecName(webrtc::kDecoderPCM16B).c_str() << std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderPCM16Bwb, + FLAGS_pcm16b_wb); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_pcm16b_wb << + " as " << CodecName(webrtc::kDecoderPCM16Bwb).c_str() << std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderPCM16Bswb32kHz, + FLAGS_pcm16b_swb32); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_pcm16b_swb32 << + " as " << CodecName(webrtc::kDecoderPCM16Bswb32kHz).c_str() << + std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderPCM16Bswb48kHz, + FLAGS_pcm16b_swb48); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_pcm16b_swb48 << + " as " << CodecName(webrtc::kDecoderPCM16Bswb48kHz).c_str() << + std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderG722, FLAGS_g722); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_g722 << + " as " << CodecName(webrtc::kDecoderG722).c_str() << std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderAVT, FLAGS_avt); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_avt << + " as " << CodecName(webrtc::kDecoderAVT).c_str() << std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderRED, FLAGS_red); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_red << + " as " << CodecName(webrtc::kDecoderRED).c_str() << std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderCNGnb, FLAGS_cn_nb); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_cn_nb << + " as " << CodecName(webrtc::kDecoderCNGnb).c_str() << std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderCNGwb, FLAGS_cn_wb); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_cn_wb << + " as " << CodecName(webrtc::kDecoderCNGwb).c_str() << std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderCNGswb32kHz, + FLAGS_cn_swb32); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_cn_swb32 << + " as " << CodecName(webrtc::kDecoderCNGswb32kHz).c_str() << std::endl; + exit(1); + } + error = neteq->RegisterPayloadType(webrtc::kDecoderCNGswb48kHz, + FLAGS_cn_swb48); + if (error) { + std::cerr << "Cannot register payload type " << FLAGS_cn_swb48 << + " as " << CodecName(webrtc::kDecoderCNGswb48kHz).c_str() << std::endl; + exit(1); + } +} + +void PrintCodecMapping() { + std::cout << CodecName(webrtc::kDecoderPCMu).c_str() << ": " << FLAGS_pcmu << + std::endl; + std::cout << CodecName(webrtc::kDecoderPCMa).c_str() << ": " << FLAGS_pcma << + std::endl; + std::cout << CodecName(webrtc::kDecoderILBC).c_str() << ": " << FLAGS_ilbc << + std::endl; + std::cout << CodecName(webrtc::kDecoderISAC).c_str() << ": " << FLAGS_isac << + std::endl; + std::cout << CodecName(webrtc::kDecoderISACswb).c_str() << ": " << + FLAGS_isac_swb << std::endl; + std::cout << CodecName(webrtc::kDecoderPCM16B).c_str() << ": " << + FLAGS_pcm16b << std::endl; + std::cout << CodecName(webrtc::kDecoderPCM16Bwb).c_str() << ": " << + FLAGS_pcm16b_wb << std::endl; + std::cout << CodecName(webrtc::kDecoderPCM16Bswb32kHz).c_str() << ": " << + FLAGS_pcm16b_swb32 << std::endl; + std::cout << CodecName(webrtc::kDecoderPCM16Bswb48kHz).c_str() << ": " << + FLAGS_pcm16b_swb48 << std::endl; + std::cout << CodecName(webrtc::kDecoderG722).c_str() << ": " << FLAGS_g722 << + std::endl; + std::cout << CodecName(webrtc::kDecoderAVT).c_str() << ": " << FLAGS_avt << + std::endl; + std::cout << CodecName(webrtc::kDecoderRED).c_str() << ": " << FLAGS_red << + std::endl; + std::cout << CodecName(webrtc::kDecoderCNGnb).c_str() << ": " << + FLAGS_cn_nb << std::endl; + std::cout << CodecName(webrtc::kDecoderCNGwb).c_str() << ": " << + FLAGS_cn_wb << std::endl; + std::cout << CodecName(webrtc::kDecoderCNGswb32kHz).c_str() << ": " << + FLAGS_cn_swb32 << std::endl; + std::cout << CodecName(webrtc::kDecoderCNGswb48kHz).c_str() << ": " << + FLAGS_cn_swb48 << std::endl; +} + +size_t ReplacePayload(webrtc::test::InputAudioFile* replacement_audio_file, + webrtc::scoped_ptr<int16_t[]>* replacement_audio, + webrtc::scoped_ptr<uint8_t[]>* payload, + size_t* payload_mem_size_bytes, + size_t* frame_size_samples, + WebRtcRTPHeader* rtp_header, + NETEQTEST_RTPpacket* next_rtp) { + size_t payload_len = 0; + // Check for CNG. + if (IsComfortNosie(rtp_header->header.payloadType)) { + // If CNG, simply insert a zero-energy one-byte payload. + if (*payload_mem_size_bytes < 1) { + (*payload).reset(new uint8_t[1]); + *payload_mem_size_bytes = 1; + } + (*payload)[0] = 127; // Max attenuation of CNG. + payload_len = 1; + } else { + if (next_rtp->payloadLen() > 0) { + // Check if payload length has changed. + if (next_rtp->sequenceNumber() == rtp_header->header.sequenceNumber + 1) { + if (*frame_size_samples != + next_rtp->timeStamp() - rtp_header->header.timestamp) { + *frame_size_samples = + next_rtp->timeStamp() - rtp_header->header.timestamp; + (*replacement_audio).reset( + new int16_t[*frame_size_samples]); + *payload_mem_size_bytes = 2 * *frame_size_samples; + (*payload).reset(new uint8_t[*payload_mem_size_bytes]); + } + } + } + // Get new speech. + assert((*replacement_audio).get()); + if (CodecTimestampRate(rtp_header->header.payloadType) != + CodecSampleRate(rtp_header->header.payloadType) || + rtp_header->header.payloadType == FLAGS_red || + rtp_header->header.payloadType == FLAGS_avt) { + // Some codecs have different sample and timestamp rates. And neither + // RED nor DTMF is supported for replacement. + std::cerr << "Codec not supported for audio replacement." << + std::endl; + webrtc::Trace::ReturnTrace(); + exit(1); + } + assert(*frame_size_samples > 0); + if (!replacement_audio_file->Read(*frame_size_samples, + (*replacement_audio).get())) { + std::cerr << "Could no read replacement audio file." << std::endl; + webrtc::Trace::ReturnTrace(); + exit(1); + } + // Encode it as PCM16. + assert((*payload).get()); + payload_len = WebRtcPcm16b_Encode((*replacement_audio).get(), + static_cast<int16_t>(*frame_size_samples), + (*payload).get()); + assert(payload_len == 2 * *frame_size_samples); + // Change payload type to PCM16. + switch (CodecSampleRate(rtp_header->header.payloadType)) { + case 8000: + rtp_header->header.payloadType = FLAGS_pcm16b; + break; + case 16000: + rtp_header->header.payloadType = FLAGS_pcm16b_wb; + break; + case 32000: + rtp_header->header.payloadType = FLAGS_pcm16b_swb32; + break; + case 48000: + rtp_header->header.payloadType = FLAGS_pcm16b_swb48; + break; + default: + std::cerr << "Payload type " << + static_cast<int>(rtp_header->header.payloadType) << + " not supported or unknown." << std::endl; + webrtc::Trace::ReturnTrace(); + exit(1); + assert(false); + } + } + return payload_len; +} + +int CodecSampleRate(uint8_t payload_type) { + if (payload_type == FLAGS_pcmu || + payload_type == FLAGS_pcma || + payload_type == FLAGS_ilbc || + payload_type == FLAGS_pcm16b || + payload_type == FLAGS_cn_nb) { + return 8000; + } else if (payload_type == FLAGS_isac || + payload_type == FLAGS_pcm16b_wb || + payload_type == FLAGS_g722 || + payload_type == FLAGS_cn_wb) { + return 16000; + } else if (payload_type == FLAGS_isac_swb || + payload_type == FLAGS_pcm16b_swb32 || + payload_type == FLAGS_cn_swb32) { + return 32000; + } else if (payload_type == FLAGS_pcm16b_swb48 || + payload_type == FLAGS_cn_swb48) { + return 48000; + } else if (payload_type == FLAGS_avt || + payload_type == FLAGS_red) { + return 0; + } else { + return -1; + } +} + +int CodecTimestampRate(uint8_t payload_type) { + if (payload_type == FLAGS_g722) { + return 8000; + } else { + return CodecSampleRate(payload_type); + } +} + +bool IsComfortNosie(uint8_t payload_type) { + if (payload_type == FLAGS_cn_nb || + payload_type == FLAGS_cn_wb || + payload_type == FLAGS_cn_swb32 || + payload_type == FLAGS_cn_swb48) { + return true; + } else { + return false; + } +} |