Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_coding / neteq4 / tools / neteq_rtpplay.cc
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/neteq4/interface/neteq.h"
24 #include "webrtc/modules/audio_coding/neteq4/test/NETEQTEST_RTPpacket.h"
25 #include "webrtc/modules/audio_coding/neteq4/test/NETEQTEST_DummyRTPpacket.h"
26 #include "webrtc/modules/audio_coding/neteq4/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 }