Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_coding / neteq / 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/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
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_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).
99 std::string CodecName(webrtc::NetEqDecoder codec);
100 void RegisterPayloadTypes(NetEq* neteq);
101 void PrintCodecMapping();
102 size_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);
109 int CodecSampleRate(uint8_t payload_type);
110 int CodecTimestampRate(uint8_t payload_type);
111 bool IsComfortNosie(uint8_t payload_type);
112
113 int 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.
306 std::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|.
347 void 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
455 void 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
490 size_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
573 int 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
600 int CodecTimestampRate(uint8_t payload_type) {
601   if (payload_type == FLAGS_g722) {
602     return 8000;
603   } else {
604     return CodecSampleRate(payload_type);
605   }
606 }
607
608 bool 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 }