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