+
+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;
+ }
+}