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
33using webrtc::NetEq;
34using webrtc::WebRtcRTPHeader;
35
36// Flag validators.
37static 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.
45DEFINE_int32(pcmu, 0, "RTP payload type for PCM-u");
46static const bool pcmu_dummy =
47    google::RegisterFlagValidator(&FLAGS_pcmu, &ValidatePayloadType);
48DEFINE_int32(pcma, 8, "RTP payload type for PCM-a");
49static const bool pcma_dummy =
50    google::RegisterFlagValidator(&FLAGS_pcma, &ValidatePayloadType);
51DEFINE_int32(ilbc, 102, "RTP payload type for iLBC");
52static const bool ilbc_dummy =
53    google::RegisterFlagValidator(&FLAGS_ilbc, &ValidatePayloadType);
54DEFINE_int32(isac, 103, "RTP payload type for iSAC");
55static const bool isac_dummy =
56    google::RegisterFlagValidator(&FLAGS_isac, &ValidatePayloadType);
57DEFINE_int32(isac_swb, 104, "RTP payload type for iSAC-swb (32 kHz)");
58static const bool isac_swb_dummy =
59    google::RegisterFlagValidator(&FLAGS_isac_swb, &ValidatePayloadType);
60DEFINE_int32(pcm16b, 93, "RTP payload type for PCM16b-nb (8 kHz)");
61static const bool pcm16b_dummy =
62    google::RegisterFlagValidator(&FLAGS_pcm16b, &ValidatePayloadType);
63DEFINE_int32(pcm16b_wb, 94, "RTP payload type for PCM16b-wb (16 kHz)");
64static const bool pcm16b_wb_dummy =
65    google::RegisterFlagValidator(&FLAGS_pcm16b_wb, &ValidatePayloadType);
66DEFINE_int32(pcm16b_swb32, 95, "RTP payload type for PCM16b-swb32 (32 kHz)");
67static const bool pcm16b_swb32_dummy =
68    google::RegisterFlagValidator(&FLAGS_pcm16b_swb32, &ValidatePayloadType);
69DEFINE_int32(pcm16b_swb48, 96, "RTP payload type for PCM16b-swb48 (48 kHz)");
70static const bool pcm16b_swb48_dummy =
71    google::RegisterFlagValidator(&FLAGS_pcm16b_swb48, &ValidatePayloadType);
72DEFINE_int32(g722, 9, "RTP payload type for G.722");
73static const bool g722_dummy =
74    google::RegisterFlagValidator(&FLAGS_g722, &ValidatePayloadType);
75DEFINE_int32(avt, 106, "RTP payload type for AVT/DTMF");
76static const bool avt_dummy =
77    google::RegisterFlagValidator(&FLAGS_avt, &ValidatePayloadType);
78DEFINE_int32(red, 117, "RTP payload type for redundant audio (RED)");
79static const bool red_dummy =
80    google::RegisterFlagValidator(&FLAGS_red, &ValidatePayloadType);
81DEFINE_int32(cn_nb, 13, "RTP payload type for comfort noise (8 kHz)");
82static const bool cn_nb_dummy =
83    google::RegisterFlagValidator(&FLAGS_cn_nb, &ValidatePayloadType);
84DEFINE_int32(cn_wb, 98, "RTP payload type for comfort noise (16 kHz)");
85static const bool cn_wb_dummy =
86    google::RegisterFlagValidator(&FLAGS_cn_wb, &ValidatePayloadType);
87DEFINE_int32(cn_swb32, 99, "RTP payload type for comfort noise (32 kHz)");
88static const bool cn_swb32_dummy =
89    google::RegisterFlagValidator(&FLAGS_cn_swb32, &ValidatePayloadType);
90DEFINE_int32(cn_swb48, 100, "RTP payload type for comfort noise (48 kHz)");
91static const bool cn_swb48_dummy =
92    google::RegisterFlagValidator(&FLAGS_cn_swb48, &ValidatePayloadType);
93DEFINE_bool(codec_map, false, "Prints the mapping between RTP payload type and "
94    "codec");
95DEFINE_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).
99std::string CodecName(webrtc::NetEqDecoder codec);
100void RegisterPayloadTypes(NetEq* neteq);
101void PrintCodecMapping();
102size_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);
109int CodecSampleRate(uint8_t payload_type);
110int CodecTimestampRate(uint8_t payload_type);
111bool IsComfortNosie(uint8_t payload_type);
112
113int 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.
306std::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|.
347void 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
455void 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
490size_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
573int 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
600int CodecTimestampRate(uint8_t payload_type) {
601  if (payload_type == FLAGS_g722) {
602    return 8000;
603  } else {
604    return CodecSampleRate(payload_type);
605  }
606}
607
608bool 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}
618