Replacing the legacy tool RTPencode with a new rtp_encode
This new tool provides the same functionality as the legacy tool, but it
is implemented using AudioCodingModule and AudioEncoder APIs instead of
the naked codecs.
Bug: webrtc:2692
Change-Id: I29accd77d4ba5c7b5e1559853cbaf20ee812e6bc
Reviewed-on: https://webrtc-review.googlesource.com/24861
Commit-Queue: Henrik Lundin <henrik.lundin@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20857}
diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn
index 871cbe9..a0b1525 100644
--- a/modules/audio_coding/BUILD.gn
+++ b/modules/audio_coding/BUILD.gn
@@ -1190,7 +1190,6 @@
testonly = true
public_deps = [
":RTPchange",
- ":RTPencode",
":RTPjitter",
":RTPtimeshift",
":acm_receive_test",
@@ -1213,6 +1212,7 @@
":neteq_pcmu_quality_test",
":neteq_speed_test",
":rtp_analyze",
+ ":rtp_encode",
":rtpcat",
":webrtc_opus_fec_test",
]
@@ -1645,65 +1645,27 @@
}
}
- config("RTPencode_config") {
- defines = [
- "CODEC_ILBC",
- "CODEC_PCM16B",
- "CODEC_G711",
- "CODEC_G722",
- "CODEC_ISAC",
- "CODEC_PCM16B_WB",
- "CODEC_ISAC_SWB",
- "CODEC_PCM16B_32KHZ",
- "CODEC_PCM16B_48KHZ",
- "CODEC_CNGCODEC8",
- "CODEC_CNGCODEC16",
- "CODEC_CNGCODEC32",
- "CODEC_ATEVENT_DECODE",
- "CODEC_RED",
- "CODEC_OPUS",
- ]
- }
-
- rtc_executable("RTPencode") {
+ rtc_executable("rtp_encode") {
testonly = true
- deps = [
- # TODO(hlundin): Make RTPencode use ACM to encode files.
- ":cng",
- ":g711",
- ":g722",
- ":ilbc",
- ":isac",
- ":neteq",
- ":neteq_test_tools_deprecated",
- ":pcm16b",
- ":webrtc_opus",
- "../..:webrtc_common",
- "../../common_audio",
- "../../rtc_base:rtc_base_approved",
- "../../system_wrappers:metrics_default",
- "../../test:field_trial",
- ]
-
- configs += [ ":RTPencode_config" ]
+ deps = audio_coding_deps + [
+ ":audio_coding",
+ ":neteq_input_audio_tools",
+ "../../api/audio_codecs/g711:audio_encoder_g711",
+ "../../api/audio_codecs/L16:audio_encoder_L16",
+ "../../api/audio_codecs/g722:audio_encoder_g722",
+ "../../api/audio_codecs/ilbc:audio_encoder_ilbc",
+ "../../api/audio_codecs/isac:audio_encoder_isac",
+ "../../api/audio_codecs/opus:audio_encoder_opus",
+ "../../rtc_base:rtc_base_approved",
+ "../../system_wrappers:system_wrappers_default",
+ ]
sources = [
- "neteq/test/PayloadTypes.h",
- "neteq/test/RTPencode.cc",
+ "neteq/tools/rtp_encode.cc",
]
- include_dirs = [
- "neteq/include",
- "neteq/test",
- ]
-
- if (is_win) {
- cflags = [
- # Disable warnings to enable Win64 build, issue 1323.
- "/wd4267", # size_t to int truncation
- ]
- }
+ defines = audio_coding_defines
}
rtc_executable("RTPchange") {
diff --git a/modules/audio_coding/neteq/test/PayloadTypes.h b/modules/audio_coding/neteq/test/PayloadTypes.h
deleted file mode 100644
index 266595c..0000000
--- a/modules/audio_coding/neteq/test/PayloadTypes.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-/* PayloadTypes.h */
-/* Used by RTPencode application */
-// TODO(henrik.lundin) Remove this once RTPencode is refactored.
-
-/* RTP defined codepoints */
-#define NETEQ_CODEC_PCMU_PT 0
-#define NETEQ_CODEC_PCMA_PT 8
-#define NETEQ_CODEC_G722_PT 9
-#define NETEQ_CODEC_CN_PT 13
-
-/* Dynamic RTP codepoints */
-#define NETEQ_CODEC_ILBC_PT 102
-#define NETEQ_CODEC_ISAC_PT 103
-#define NETEQ_CODEC_ISACSWB_PT 104
-#define NETEQ_CODEC_AVT_PT 106
-#define NETEQ_CODEC_OPUS_PT 111
-#define NETEQ_CODEC_RED_PT 117
-#define NETEQ_CODEC_CN_WB_PT 105
-#define NETEQ_CODEC_CN_SWB_PT 126
-#define NETEQ_CODEC_PCM16B_PT 93
-#define NETEQ_CODEC_PCM16B_WB_PT 94
-#define NETEQ_CODEC_PCM16B_SWB32KHZ_PT 95
-#define NETEQ_CODEC_PCM16B_SWB48KHZ_PT 96
diff --git a/modules/audio_coding/neteq/test/RTPencode.cc b/modules/audio_coding/neteq/test/RTPencode.cc
deleted file mode 100644
index 9e3bc6c..0000000
--- a/modules/audio_coding/neteq/test/RTPencode.cc
+++ /dev/null
@@ -1,1797 +0,0 @@
-/*
- * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-// TODO(henrik.lundin): Refactor or replace all of this application.
-
-/* header includes */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef WIN32
-#include <winsock2.h>
-#endif
-#ifdef WEBRTC_LINUX
-#include <netinet/in.h>
-#endif
-
-#include <assert.h>
-
-#include <algorithm>
-
-#include "rtc_base/checks.h"
-#include "typedefs.h" // NOLINT(build/include)
-
-// needed for NetEqDecoder
-#include "modules/audio_coding/neteq/include/neteq.h"
-
-/************************/
-/* Define payload types */
-/************************/
-
-#include "PayloadTypes.h"
-
-namespace {
-const size_t kRtpDataSize = 8000;
-}
-
-/*********************/
-/* Misc. definitions */
-/*********************/
-
-#define STOPSENDTIME 3000
-#define RESTARTSENDTIME 0 // 162500
-#define FIRSTLINELEN 40
-#define CHECK_NOT_NULL(a) \
- if ((a) == 0) { \
- printf("\n %s \n line: %d \nerror at %s\n", __FILE__, __LINE__, #a); \
- return (-1); \
- }
-
-//#define MULTIPLE_SAME_TIMESTAMP
-#define REPEAT_PACKET_DISTANCE 17
-#define REPEAT_PACKET_COUNT 1 // number of extra packets to send
-
-//#define INSERT_OLD_PACKETS
-#define OLD_PACKET 5 // how many seconds too old should the packet be?
-
-//#define TIMESTAMP_WRAPAROUND
-
-//#define RANDOM_DATA
-//#define RANDOM_PAYLOAD_DATA
-#define RANDOM_SEED 10
-
-//#define INSERT_DTMF_PACKETS
-//#define NO_DTMF_OVERDUB
-#define DTMF_PACKET_INTERVAL 2000
-#define DTMF_DURATION 500
-
-#define STEREO_MODE_FRAME 0
-#define STEREO_MODE_SAMPLE_1 1 // 1 octet per sample
-#define STEREO_MODE_SAMPLE_2 2 // 2 octets per sample
-
-/*************************/
-/* Function declarations */
-/*************************/
-
-void NetEQTest_GetCodec_and_PT(char* name,
- webrtc::NetEqDecoder* codec,
- int* PT,
- size_t frameLen,
- int* fs,
- int* bitrate,
- int* useRed);
-int NetEQTest_init_coders(webrtc::NetEqDecoder coder,
- size_t enc_frameSize,
- int bitrate,
- int sampfreq,
- int vad,
- size_t numChannels);
-void defineCodecs(webrtc::NetEqDecoder* usedCodec, int* noOfCodecs);
-int NetEQTest_free_coders(webrtc::NetEqDecoder coder, size_t numChannels);
-size_t NetEQTest_encode(webrtc::NetEqDecoder coder,
- int16_t* indata,
- size_t frameLen,
- unsigned char* encoded,
- int sampleRate,
- int* vad,
- int useVAD,
- int bitrate,
- size_t numChannels);
-void makeRTPheader(unsigned char* rtp_data,
- int payloadType,
- int seqNo,
- uint32_t timestamp,
- uint32_t ssrc);
-int makeRedundantHeader(unsigned char* rtp_data,
- int* payloadType,
- int numPayloads,
- uint32_t* timestamp,
- uint16_t* blockLen,
- int seqNo,
- uint32_t ssrc);
-size_t makeDTMFpayload(unsigned char* payload_data,
- int Event,
- int End,
- int Volume,
- int Duration);
-void stereoDeInterleave(int16_t* audioSamples, size_t numSamples);
-void stereoInterleave(unsigned char* data, size_t dataLen, size_t stride);
-
-/*********************/
-/* Codec definitions */
-/*********************/
-
-#include "webrtc_vad.h"
-
-#if ((defined CODEC_PCM16B) || (defined NETEQ_ARBITRARY_CODEC))
-#include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
-#endif
-#ifdef CODEC_G711
-#include "modules/audio_coding/codecs/g711/g711_interface.h"
-#endif
-#ifdef CODEC_G729
-#include "G729Interface.h"
-#endif
-#ifdef CODEC_G729_1
-#include "G729_1Interface.h"
-#endif
-#ifdef CODEC_AMR
-#include "AMRInterface.h"
-#include "AMRCreation.h"
-#endif
-#ifdef CODEC_AMRWB
-#include "AMRWBInterface.h"
-#include "AMRWBCreation.h"
-#endif
-#ifdef CODEC_ILBC
-#include "modules/audio_coding/codecs/ilbc/ilbc.h"
-#endif
-#if (defined CODEC_ISAC || defined CODEC_ISAC_SWB)
-#include "modules/audio_coding/codecs/isac/main/include/isac.h"
-#endif
-#ifdef NETEQ_ISACFIX_CODEC
-#include "modules/audio_coding/codecs/isac/fix/include/isacfix.h"
-#ifdef CODEC_ISAC
-#error Cannot have both ISAC and ISACfix defined. Please de-select one.
-#endif
-#endif
-#ifdef CODEC_G722
-#include "modules/audio_coding/codecs/g722/g722_interface.h"
-#endif
-#ifdef CODEC_G722_1_24
-#include "G722_1Interface.h"
-#endif
-#ifdef CODEC_G722_1_32
-#include "G722_1Interface.h"
-#endif
-#ifdef CODEC_G722_1_16
-#include "G722_1Interface.h"
-#endif
-#ifdef CODEC_G722_1C_24
-#include "G722_1Interface.h"
-#endif
-#ifdef CODEC_G722_1C_32
-#include "G722_1Interface.h"
-#endif
-#ifdef CODEC_G722_1C_48
-#include "G722_1Interface.h"
-#endif
-#ifdef CODEC_G726
-#include "G726Creation.h"
-#include "G726Interface.h"
-#endif
-#ifdef CODEC_GSMFR
-#include "GSMFRInterface.h"
-#include "GSMFRCreation.h"
-#endif
-#if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \
- defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48))
-#include "modules/audio_coding/codecs/cng/webrtc_cng.h"
-#endif
-#ifdef CODEC_OPUS
-#include "modules/audio_coding/codecs/opus/opus_interface.h"
-#endif
-
-/***********************************/
-/* Global codec instance variables */
-/***********************************/
-
-WebRtcVadInst* VAD_inst[2];
-
-#ifdef CODEC_G722
-G722EncInst* g722EncState[2];
-#endif
-
-#ifdef CODEC_G722_1_24
-G722_1_24_encinst_t* G722_1_24enc_inst[2];
-#endif
-#ifdef CODEC_G722_1_32
-G722_1_32_encinst_t* G722_1_32enc_inst[2];
-#endif
-#ifdef CODEC_G722_1_16
-G722_1_16_encinst_t* G722_1_16enc_inst[2];
-#endif
-#ifdef CODEC_G722_1C_24
-G722_1C_24_encinst_t* G722_1C_24enc_inst[2];
-#endif
-#ifdef CODEC_G722_1C_32
-G722_1C_32_encinst_t* G722_1C_32enc_inst[2];
-#endif
-#ifdef CODEC_G722_1C_48
-G722_1C_48_encinst_t* G722_1C_48enc_inst[2];
-#endif
-#ifdef CODEC_G726
-G726_encinst_t* G726enc_inst[2];
-#endif
-#ifdef CODEC_G729
-G729_encinst_t* G729enc_inst[2];
-#endif
-#ifdef CODEC_G729_1
-G729_1_inst_t* G729_1_inst[2];
-#endif
-#ifdef CODEC_AMR
-AMR_encinst_t* AMRenc_inst[2];
-int16_t AMR_bitrate;
-#endif
-#ifdef CODEC_AMRWB
-AMRWB_encinst_t* AMRWBenc_inst[2];
-int16_t AMRWB_bitrate;
-#endif
-#ifdef CODEC_ILBC
-IlbcEncoderInstance* iLBCenc_inst[2];
-#endif
-#ifdef CODEC_ISAC
-ISACStruct* ISAC_inst[2];
-#endif
-#ifdef NETEQ_ISACFIX_CODEC
-ISACFIX_MainStruct* ISAC_inst[2];
-#endif
-#ifdef CODEC_ISAC_SWB
-ISACStruct* ISACSWB_inst[2];
-#endif
-#ifdef CODEC_GSMFR
-GSMFR_encinst_t* GSMFRenc_inst[2];
-#endif
-#if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \
- defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48))
-webrtc::ComfortNoiseEncoder *CNG_encoder[2];
-#endif
-#ifdef CODEC_OPUS
-OpusEncInst* opus_inst[2];
-#endif
-
-int main(int argc, char* argv[]) {
- size_t packet_size;
- int fs;
- webrtc::NetEqDecoder usedCodec;
- int payloadType;
- int bitrate = 0;
- int useVAD, vad;
- int useRed = 0;
- size_t len, enc_len;
- int16_t org_data[4000];
- unsigned char rtp_data[kRtpDataSize];
- int16_t seqNo = 0xFFF;
- uint32_t ssrc = 1235412312;
- uint32_t timestamp = 0xAC1245;
- uint16_t length, plen;
- uint32_t offset;
- double sendtime = 0;
- int red_PT[2] = {0};
- uint32_t red_TS[2] = {0};
- uint16_t red_len[2] = {0};
- size_t RTPheaderLen = 12;
- uint8_t red_data[kRtpDataSize];
-#ifdef INSERT_OLD_PACKETS
- uint16_t old_length, old_plen;
- size_t old_enc_len;
- int first_old_packet = 1;
- unsigned char old_rtp_data[kRtpDataSize];
- size_t packet_age = 0;
-#endif
-#ifdef INSERT_DTMF_PACKETS
- int NTone = 1;
- int DTMFfirst = 1;
- uint32_t DTMFtimestamp;
- bool dtmfSent = false;
-#endif
- bool usingStereo = false;
- size_t stereoMode = 0;
- size_t numChannels = 1;
-
- /* check number of parameters */
- if ((argc != 6) && (argc != 7)) {
- /* print help text and exit */
- printf("Application to encode speech into an RTP stream.\n");
- printf("The program reads a PCM file and encodes is using the specified "
- "codec.\n");
- printf(
- "The coded speech is packetized in RTP packets and written to the "
- "output file.\n");
- printf("The format of the RTP stream file is simlilar to that of "
- "rtpplay,\n");
- printf("but with the receive time euqal to 0 for all packets.\n");
- printf("Usage:\n\n");
- printf("%s PCMfile RTPfile frameLen codec useVAD bitrate\n", argv[0]);
- printf("where:\n");
-
- printf("PCMfile : PCM speech input file\n\n");
-
- printf("RTPfile : RTP stream output file\n\n");
-
- printf("frameLen : 80...960... Number of samples per packet (limit "
- "depends on codec)\n\n");
-
- printf("codecName\n");
-#ifdef CODEC_PCM16B
- printf(" : pcm16b 16 bit PCM (8kHz)\n");
-#endif
-#ifdef CODEC_PCM16B_WB
- printf(" : pcm16b_wb 16 bit PCM (16kHz)\n");
-#endif
-#ifdef CODEC_PCM16B_32KHZ
- printf(" : pcm16b_swb32 16 bit PCM (32kHz)\n");
-#endif
-#ifdef CODEC_PCM16B_48KHZ
- printf(" : pcm16b_swb48 16 bit PCM (48kHz)\n");
-#endif
-#ifdef CODEC_G711
- printf(" : pcma g711 A-law (8kHz)\n");
-#endif
-#ifdef CODEC_G711
- printf(" : pcmu g711 u-law (8kHz)\n");
-#endif
-#ifdef CODEC_G729
- printf(" : g729 G729 (8kHz and 8kbps) CELP (One-Three "
- "frame(s)/packet)\n");
-#endif
-#ifdef CODEC_G729_1
- printf(" : g729.1 G729.1 (16kHz) variable rate (8--32 "
- "kbps)\n");
-#endif
-#ifdef CODEC_G722_1_16
- printf(" : g722.1_16 G722.1 coder (16kHz) (g722.1 with "
- "16kbps)\n");
-#endif
-#ifdef CODEC_G722_1_24
- printf(" : g722.1_24 G722.1 coder (16kHz) (the 24kbps "
- "version)\n");
-#endif
-#ifdef CODEC_G722_1_32
- printf(" : g722.1_32 G722.1 coder (16kHz) (the 32kbps "
- "version)\n");
-#endif
-#ifdef CODEC_G722_1C_24
- printf(" : g722.1C_24 G722.1 C coder (32kHz) (the 24kbps "
- "version)\n");
-#endif
-#ifdef CODEC_G722_1C_32
- printf(" : g722.1C_32 G722.1 C coder (32kHz) (the 32kbps "
- "version)\n");
-#endif
-#ifdef CODEC_G722_1C_48
- printf(" : g722.1C_48 G722.1 C coder (32kHz) (the 48kbps "
- "version)\n");
-#endif
-
-#ifdef CODEC_G726
- printf(" : g726_16 G726 coder (8kHz) 16kbps\n");
- printf(" : g726_24 G726 coder (8kHz) 24kbps\n");
- printf(" : g726_32 G726 coder (8kHz) 32kbps\n");
- printf(" : g726_40 G726 coder (8kHz) 40kbps\n");
-#endif
-#ifdef CODEC_AMR
- printf(" : AMRXk Adaptive Multi Rate CELP codec "
- "(8kHz)\n");
- printf(" X = 4.75, 5.15, 5.9, 6.7, 7.4, 7.95, "
- "10.2 or 12.2\n");
-#endif
-#ifdef CODEC_AMRWB
- printf(" : AMRwbXk Adaptive Multi Rate Wideband CELP "
- "codec (16kHz)\n");
- printf(" X = 7, 9, 12, 14, 16, 18, 20, 23 or "
- "24\n");
-#endif
-#ifdef CODEC_ILBC
- printf(" : ilbc iLBC codec (8kHz and 13.8kbps)\n");
-#endif
-#ifdef CODEC_ISAC
- printf(" : isac iSAC (16kHz and 32.0 kbps). To set "
- "rate specify a rate parameter as last parameter\n");
-#endif
-#ifdef CODEC_ISAC_SWB
- printf(" : isacswb iSAC SWB (32kHz and 32.0-52.0 kbps). "
- "To set rate specify a rate parameter as last parameter\n");
-#endif
-#ifdef CODEC_GSMFR
- printf(" : gsmfr GSM FR codec (8kHz and 13kbps)\n");
-#endif
-#ifdef CODEC_G722
- printf(" : g722 g722 coder (16kHz) (the 64kbps "
- "version)\n");
-#endif
-#ifdef CODEC_RED
-#ifdef CODEC_G711
- printf(" : red_pcm Redundancy RTP packet with 2*G711A "
- "frames\n");
-#endif
-#ifdef CODEC_ISAC
- printf(" : red_isac Redundancy RTP packet with 2*iSAC "
- "frames\n");
-#endif
-#endif // CODEC_RED
-#ifdef CODEC_OPUS
- printf(" : opus Opus codec with FEC (48kHz, 32kbps, FEC"
- " on and tuned for 5%% packet losses)\n");
-#endif
- printf("\n");
-
-#if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \
- defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48))
- printf("useVAD : 0 Voice Activity Detection is switched off\n");
- printf(" : 1 Voice Activity Detection is switched on\n\n");
-#else
- printf("useVAD : 0 Voice Activity Detection switched off (on not "
- "supported)\n\n");
-#endif
- printf("bitrate : Codec bitrate in bps (only applies to vbr "
- "codecs)\n\n");
-
- return (0);
- }
-
- FILE* in_file = fopen(argv[1], "rb");
- CHECK_NOT_NULL(in_file);
- printf("Input file: %s\n", argv[1]);
- FILE* out_file = fopen(argv[2], "wb");
- CHECK_NOT_NULL(out_file);
- printf("Output file: %s\n\n", argv[2]);
- int packet_size_int = atoi(argv[3]);
- if (packet_size_int <= 0) {
- printf("Packet size %d must be positive", packet_size_int);
- return -1;
- }
- printf("Packet size: %d\n", packet_size_int);
- packet_size = static_cast<size_t>(packet_size_int);
-
- // check for stereo
- if (argv[4][strlen(argv[4]) - 1] == '*') {
- // use stereo
- usingStereo = true;
- numChannels = 2;
- argv[4][strlen(argv[4]) - 1] = '\0';
- }
-
- NetEQTest_GetCodec_and_PT(argv[4], &usedCodec, &payloadType, packet_size, &fs,
- &bitrate, &useRed);
-
- if (useRed) {
- RTPheaderLen = 12 + 4 + 1; /* standard RTP = 12; 4 bytes per redundant
- payload, except last one which is 1 byte */
- }
-
- useVAD = atoi(argv[5]);
-#if !(defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \
- defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48))
- if (useVAD != 0) {
- printf("Error: this simulation does not support VAD/DTX/CNG\n");
- }
-#endif
-
- // check stereo type
- if (usingStereo) {
- switch (usedCodec) {
- // sample based codecs
- case webrtc::NetEqDecoder::kDecoderPCMu:
- case webrtc::NetEqDecoder::kDecoderPCMa:
- case webrtc::NetEqDecoder::kDecoderG722: {
- // 1 octet per sample
- stereoMode = STEREO_MODE_SAMPLE_1;
- break;
- }
- case webrtc::NetEqDecoder::kDecoderPCM16B:
- case webrtc::NetEqDecoder::kDecoderPCM16Bwb:
- case webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz:
- case webrtc::NetEqDecoder::kDecoderPCM16Bswb48kHz: {
- // 2 octets per sample
- stereoMode = STEREO_MODE_SAMPLE_2;
- break;
- }
-
- // fixed-rate frame codecs (with internal VAD)
- default: {
- printf("Cannot use codec %s as stereo codec\n", argv[4]);
- exit(0);
- }
- }
- }
-
- if ((usedCodec == webrtc::NetEqDecoder::kDecoderISAC) ||
- (usedCodec == webrtc::NetEqDecoder::kDecoderISACswb)) {
- if (argc != 7) {
- if (usedCodec == webrtc::NetEqDecoder::kDecoderISAC) {
- bitrate = 32000;
- printf("Running iSAC at default bitrate of 32000 bps (to specify "
- "explicitly add the bps as last parameter)\n");
- } else // (usedCodec==webrtc::kDecoderISACswb)
- {
- bitrate = 56000;
- printf("Running iSAC at default bitrate of 56000 bps (to specify "
- "explicitly add the bps as last parameter)\n");
- }
- } else {
- bitrate = atoi(argv[6]);
- if (usedCodec == webrtc::NetEqDecoder::kDecoderISAC) {
- if ((bitrate < 10000) || (bitrate > 32000)) {
- printf("Error: iSAC bitrate must be between 10000 and 32000 bps (%i "
- "is invalid)\n", bitrate);
- exit(0);
- }
- printf("Running iSAC at bitrate of %i bps\n", bitrate);
- } else // (usedCodec==webrtc::kDecoderISACswb)
- {
- if ((bitrate < 32000) || (bitrate > 56000)) {
- printf("Error: iSAC SWB bitrate must be between 32000 and 56000 bps "
- "(%i is invalid)\n", bitrate);
- exit(0);
- }
- }
- }
- } else {
- if (argc == 7) {
- printf("Error: Bitrate parameter can only be specified for iSAC, G.723, "
- "and G.729.1\n");
- exit(0);
- }
- }
-
- if (useRed) {
- printf("Redundancy engaged. ");
- }
- printf("Used codec: %i\n", static_cast<int>(usedCodec));
- printf("Payload type: %i\n", payloadType);
-
- NetEQTest_init_coders(usedCodec, packet_size, bitrate, fs, useVAD,
- numChannels);
-
- /* write file header */
- // fprintf(out_file, "#!RTPencode%s\n", "1.0");
- fprintf(out_file, "#!rtpplay%s \n",
- "1.0"); // this is the string that rtpplay needs
- uint32_t dummy_variable = 0; // should be converted to network endian format,
- // but does not matter when 0
- if (fwrite(&dummy_variable, 4, 1, out_file) != 1) {
- return -1;
- }
- if (fwrite(&dummy_variable, 4, 1, out_file) != 1) {
- return -1;
- }
- if (fwrite(&dummy_variable, 4, 1, out_file) != 1) {
- return -1;
- }
- if (fwrite(&dummy_variable, 2, 1, out_file) != 1) {
- return -1;
- }
- if (fwrite(&dummy_variable, 2, 1, out_file) != 1) {
- return -1;
- }
-
-#ifdef TIMESTAMP_WRAPAROUND
- timestamp = 0xFFFFFFFF - fs * 10; /* should give wrap-around in 10 seconds */
-#endif
-#if defined(RANDOM_DATA) | defined(RANDOM_PAYLOAD_DATA)
- srand(RANDOM_SEED);
-#endif
-
- /* if redundancy is used, the first redundant payload is zero length */
- red_len[0] = 0;
-
- /* read first frame */
- len = fread(org_data, 2, packet_size * numChannels, in_file) / numChannels;
-
- /* de-interleave if stereo */
- if (usingStereo) {
- stereoDeInterleave(org_data, len * numChannels);
- }
-
- while (len == packet_size) {
-#ifdef INSERT_DTMF_PACKETS
- dtmfSent = false;
-
- if (sendtime >= NTone * DTMF_PACKET_INTERVAL) {
- if (sendtime < NTone * DTMF_PACKET_INTERVAL + DTMF_DURATION) {
- // tone has not ended
- if (DTMFfirst == 1) {
- DTMFtimestamp = timestamp; // save this timestamp
- DTMFfirst = 0;
- }
- makeRTPheader(rtp_data, NETEQ_CODEC_AVT_PT, seqNo, DTMFtimestamp, ssrc);
- enc_len = makeDTMFpayload(
- &rtp_data[12], NTone % 12, 0, 4,
- (int)(sendtime - NTone * DTMF_PACKET_INTERVAL) * (fs / 1000) + len);
- } else {
- // tone has ended
- makeRTPheader(rtp_data, NETEQ_CODEC_AVT_PT, seqNo, DTMFtimestamp, ssrc);
- enc_len = makeDTMFpayload(&rtp_data[12], NTone % 12, 1, 4,
- DTMF_DURATION * (fs / 1000));
- NTone++;
- DTMFfirst = 1;
- }
-
- /* write RTP packet to file */
- length = htons(static_cast<unsigned short>(12 + enc_len + 8));
- plen = htons(static_cast<unsigned short>(12 + enc_len));
- offset = (uint32_t)sendtime; //(timestamp/(fs/1000));
- offset = htonl(offset);
- if (fwrite(&length, 2, 1, out_file) != 1) {
- return -1;
- }
- if (fwrite(&plen, 2, 1, out_file) != 1) {
- return -1;
- }
- if (fwrite(&offset, 4, 1, out_file) != 1) {
- return -1;
- }
- if (fwrite(rtp_data, 12 + enc_len, 1, out_file) != 1) {
- return -1;
- }
-
- dtmfSent = true;
- }
-#endif
-
-#ifdef NO_DTMF_OVERDUB
- /* If DTMF is sent, we should not send any speech packets during the same
- * time */
- if (dtmfSent) {
- enc_len = 0;
- } else {
-#endif
- /* encode frame */
- enc_len =
- NetEQTest_encode(usedCodec, org_data, packet_size, &rtp_data[12], fs,
- &vad, useVAD, bitrate, numChannels);
-
- if (usingStereo && stereoMode != STEREO_MODE_FRAME && vad == 1) {
- // interleave the encoded payload for sample-based codecs (not for CNG)
- stereoInterleave(&rtp_data[12], enc_len, stereoMode);
- }
-#ifdef NO_DTMF_OVERDUB
- }
-#endif
-
- if (enc_len > 0 &&
- (sendtime <= STOPSENDTIME || sendtime > RESTARTSENDTIME)) {
- if (useRed) {
- if (red_len[0] > 0) {
- memmove(&rtp_data[RTPheaderLen + red_len[0]], &rtp_data[12], enc_len);
- memcpy(&rtp_data[RTPheaderLen], red_data, red_len[0]);
-
- red_len[1] = static_cast<uint16_t>(enc_len);
- red_TS[1] = timestamp;
- if (vad)
- red_PT[1] = payloadType;
- else
- red_PT[1] = NETEQ_CODEC_CN_PT;
-
- makeRedundantHeader(rtp_data, red_PT, 2, red_TS, red_len, seqNo++,
- ssrc);
-
- enc_len += red_len[0] + RTPheaderLen - 12;
- } else { // do not use redundancy payload for this packet, i.e., only
- // last payload
- memmove(&rtp_data[RTPheaderLen - 4], &rtp_data[12], enc_len);
- // memcpy(&rtp_data[RTPheaderLen], red_data, red_len[0]);
-
- red_len[1] = static_cast<uint16_t>(enc_len);
- red_TS[1] = timestamp;
- if (vad)
- red_PT[1] = payloadType;
- else
- red_PT[1] = NETEQ_CODEC_CN_PT;
-
- makeRedundantHeader(rtp_data, red_PT, 2, red_TS, red_len, seqNo++,
- ssrc);
-
- enc_len += red_len[0] + RTPheaderLen - 4 -
- 12; // 4 is length of redundancy header (not used)
- }
- } else {
- /* make RTP header */
- if (vad) // regular speech data
- makeRTPheader(rtp_data, payloadType, seqNo++, timestamp, ssrc);
- else // CNG data
- makeRTPheader(rtp_data, NETEQ_CODEC_CN_PT, seqNo++, timestamp, ssrc);
- }
-#ifdef MULTIPLE_SAME_TIMESTAMP
- int mult_pack = 0;
- do {
-#endif // MULTIPLE_SAME_TIMESTAMP
- /* write RTP packet to file */
- length = htons(static_cast<unsigned short>(12 + enc_len + 8));
- plen = htons(static_cast<unsigned short>(12 + enc_len));
- offset = (uint32_t)sendtime;
- //(timestamp/(fs/1000));
- offset = htonl(offset);
- if (fwrite(&length, 2, 1, out_file) != 1) {
- return -1;
- }
- if (fwrite(&plen, 2, 1, out_file) != 1) {
- return -1;
- }
- if (fwrite(&offset, 4, 1, out_file) != 1) {
- return -1;
- }
-#ifdef RANDOM_DATA
- for (size_t k = 0; k < 12 + enc_len; k++) {
- rtp_data[k] = rand() + rand();
- }
-#endif
-#ifdef RANDOM_PAYLOAD_DATA
- for (size_t k = 12; k < 12 + enc_len; k++) {
- rtp_data[k] = rand() + rand();
- }
-#endif
- if (fwrite(rtp_data, 12 + enc_len, 1, out_file) != 1) {
- return -1;
- }
-#ifdef MULTIPLE_SAME_TIMESTAMP
- } while ((seqNo % REPEAT_PACKET_DISTANCE == 0) &&
- (mult_pack++ < REPEAT_PACKET_COUNT));
-#endif // MULTIPLE_SAME_TIMESTAMP
-
-#ifdef INSERT_OLD_PACKETS
- if (packet_age >= OLD_PACKET * fs) {
- if (!first_old_packet) {
- // send the old packet
- if (fwrite(&old_length, 2, 1, out_file) != 1) {
- return -1;
- }
- if (fwrite(&old_plen, 2, 1, out_file) != 1) {
- return -1;
- }
- if (fwrite(&offset, 4, 1, out_file) != 1) {
- return -1;
- }
- if (fwrite(old_rtp_data, 12 + old_enc_len, 1, out_file) != 1) {
- return -1;
- }
- }
- // store current packet as old
- old_length = length;
- old_plen = plen;
- memcpy(old_rtp_data, rtp_data, 12 + enc_len);
- old_enc_len = enc_len;
- first_old_packet = 0;
- packet_age = 0;
- }
- packet_age += packet_size;
-#endif
-
- if (useRed) {
-/* move data to redundancy store */
-#ifdef CODEC_ISAC
- if (usedCodec == webrtc::NetEqDecoder::kDecoderISAC) {
- assert(!usingStereo); // Cannot handle stereo yet
- red_len[0] = WebRtcIsac_GetRedPayload(ISAC_inst[0], red_data);
- } else {
-#endif
- memcpy(red_data, &rtp_data[RTPheaderLen + red_len[0]], enc_len);
- red_len[0] = red_len[1];
-#ifdef CODEC_ISAC
- }
-#endif
- red_TS[0] = red_TS[1];
- red_PT[0] = red_PT[1];
- }
- }
-
- /* read next frame */
- len = fread(org_data, 2, packet_size * numChannels, in_file) / numChannels;
- /* de-interleave if stereo */
- if (usingStereo) {
- stereoDeInterleave(org_data, len * numChannels);
- }
-
- if (payloadType == NETEQ_CODEC_G722_PT)
- timestamp += len >> 1;
- else
- timestamp += len;
-
- sendtime += (double)len / (fs / 1000);
- }
-
- NetEQTest_free_coders(usedCodec, numChannels);
- fclose(in_file);
- fclose(out_file);
- printf("Done!\n");
-
- return (0);
-}
-
-/****************/
-/* Subfunctions */
-/****************/
-
-void NetEQTest_GetCodec_and_PT(char* name,
- webrtc::NetEqDecoder* codec,
- int* PT,
- size_t frameLen,
- int* fs,
- int* bitrate,
- int* useRed) {
- *bitrate = 0; /* Default bitrate setting */
- *useRed = 0; /* Default no redundancy */
-
- if (!strcmp(name, "pcmu")) {
- *codec = webrtc::NetEqDecoder::kDecoderPCMu;
- *PT = NETEQ_CODEC_PCMU_PT;
- *fs = 8000;
- } else if (!strcmp(name, "pcma")) {
- *codec = webrtc::NetEqDecoder::kDecoderPCMa;
- *PT = NETEQ_CODEC_PCMA_PT;
- *fs = 8000;
- } else if (!strcmp(name, "pcm16b")) {
- *codec = webrtc::NetEqDecoder::kDecoderPCM16B;
- *PT = NETEQ_CODEC_PCM16B_PT;
- *fs = 8000;
- } else if (!strcmp(name, "pcm16b_wb")) {
- *codec = webrtc::NetEqDecoder::kDecoderPCM16Bwb;
- *PT = NETEQ_CODEC_PCM16B_WB_PT;
- *fs = 16000;
- } else if (!strcmp(name, "pcm16b_swb32")) {
- *codec = webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz;
- *PT = NETEQ_CODEC_PCM16B_SWB32KHZ_PT;
- *fs = 32000;
- } else if (!strcmp(name, "pcm16b_swb48")) {
- *codec = webrtc::NetEqDecoder::kDecoderPCM16Bswb48kHz;
- *PT = NETEQ_CODEC_PCM16B_SWB48KHZ_PT;
- *fs = 48000;
- } else if (!strcmp(name, "g722")) {
- *codec = webrtc::NetEqDecoder::kDecoderG722;
- *PT = NETEQ_CODEC_G722_PT;
- *fs = 16000;
- } else if ((!strcmp(name, "ilbc")) &&
- ((frameLen % 240 == 0) || (frameLen % 160 == 0))) {
- *fs = 8000;
- *codec = webrtc::NetEqDecoder::kDecoderILBC;
- *PT = NETEQ_CODEC_ILBC_PT;
- } else if (!strcmp(name, "isac")) {
- *fs = 16000;
- *codec = webrtc::NetEqDecoder::kDecoderISAC;
- *PT = NETEQ_CODEC_ISAC_PT;
- } else if (!strcmp(name, "isacswb")) {
- *fs = 32000;
- *codec = webrtc::NetEqDecoder::kDecoderISACswb;
- *PT = NETEQ_CODEC_ISACSWB_PT;
- } else if (!strcmp(name, "red_pcm")) {
- *codec = webrtc::NetEqDecoder::kDecoderPCMa;
- *PT = NETEQ_CODEC_PCMA_PT; /* this will be the PT for the sub-headers */
- *fs = 8000;
- *useRed = 1;
- } else if (!strcmp(name, "red_isac")) {
- *codec = webrtc::NetEqDecoder::kDecoderISAC;
- *PT = NETEQ_CODEC_ISAC_PT; /* this will be the PT for the sub-headers */
- *fs = 16000;
- *useRed = 1;
- } else if (!strcmp(name, "opus")) {
- *codec = webrtc::NetEqDecoder::kDecoderOpus;
- *PT = NETEQ_CODEC_OPUS_PT; /* this will be the PT for the sub-headers */
- *fs = 48000;
- } else {
- printf("Error: Not a supported codec (%s)\n", name);
- exit(0);
- }
-}
-
-int NetEQTest_init_coders(webrtc::NetEqDecoder coder,
- size_t enc_frameSize,
- int bitrate,
- int sampfreq,
- int vad,
- size_t numChannels) {
- int ok = 0;
-
- for (size_t k = 0; k < numChannels; k++) {
- VAD_inst[k] = WebRtcVad_Create();
- if (!VAD_inst[k]) {
- printf("Error: Couldn't allocate memory for VAD instance\n");
- exit(0);
- }
- ok = WebRtcVad_Init(VAD_inst[k]);
- if (ok == -1) {
- printf("Error: Initialization of VAD struct failed\n");
- exit(0);
- }
-
-#if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \
- defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48))
- if (sampfreq <= 16000) {
- CNG_encoder[k] = new webrtc::ComfortNoiseEncoder(sampfreq, 200, 5);
- }
-#endif
-
- switch (coder) {
-#ifdef CODEC_PCM16B
- case webrtc::NetEqDecoder::kDecoderPCM16B:
-#endif
-#ifdef CODEC_PCM16B_WB
- case webrtc::NetEqDecoder::kDecoderPCM16Bwb:
-#endif
-#ifdef CODEC_PCM16B_32KHZ
- case webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz:
-#endif
-#ifdef CODEC_PCM16B_48KHZ
- case webrtc::NetEqDecoder::kDecoderPCM16Bswb48kHz:
-#endif
-#ifdef CODEC_G711
- case webrtc::NetEqDecoder::kDecoderPCMu:
- case webrtc::NetEqDecoder::kDecoderPCMa:
-#endif
- // do nothing
- break;
-#ifdef CODEC_G729
- case webrtc::kDecoderG729:
- if (sampfreq == 8000) {
- if ((enc_frameSize == 80) || (enc_frameSize == 160) ||
- (enc_frameSize == 240) || (enc_frameSize == 320) ||
- (enc_frameSize == 400) || (enc_frameSize == 480)) {
- ok = WebRtcG729_CreateEnc(&G729enc_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for G729 encoding "
- "instance\n");
- exit(0);
- }
- } else {
- printf("\nError: g729 only supports 10, 20, 30, 40, 50 or 60 "
- "ms!!\n\n");
- exit(0);
- }
- WebRtcG729_EncoderInit(G729enc_inst[k], vad);
- if ((vad == 1) && (enc_frameSize != 80)) {
- printf("\nError - This simulation only supports VAD for G729 at "
- "10ms packets (not %" PRIuS "ms)\n", (enc_frameSize >> 3));
- }
- } else {
- printf("\nError - g729 is only developed for 8kHz \n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_G729_1
- case webrtc::kDecoderG729_1:
- if (sampfreq == 16000) {
- if ((enc_frameSize == 320) || (enc_frameSize == 640) ||
- (enc_frameSize == 960)) {
- ok = WebRtcG7291_Create(&G729_1_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for G.729.1 codec "
- "instance\n");
- exit(0);
- }
- } else {
- printf("\nError: G.729.1 only supports 20, 40 or 60 ms!!\n\n");
- exit(0);
- }
- if (!(((bitrate >= 12000) && (bitrate <= 32000) &&
- (bitrate % 2000 == 0)) ||
- (bitrate == 8000))) {
- /* must be 8, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, or 32 kbps */
- printf("\nError: G.729.1 bitrate must be 8000 or 12000--32000 in "
- "steps of 2000 bps\n");
- exit(0);
- }
- WebRtcG7291_EncoderInit(G729_1_inst[k], bitrate, 0 /* flag8kHz*/,
- 0 /*flagG729mode*/);
- } else {
- printf("\nError - G.729.1 input is always 16 kHz \n");
- exit(0);
- }
- break;
-#endif
-
-#ifdef CODEC_G722_1_16
- case webrtc::kDecoderG722_1_16:
- if (sampfreq == 16000) {
- ok = WebRtcG7221_CreateEnc16(&G722_1_16enc_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for G.722.1 instance\n");
- exit(0);
- }
- if (enc_frameSize == 320) {
- } else {
- printf("\nError: G722.1 only supports 20 ms!!\n\n");
- exit(0);
- }
- WebRtcG7221_EncoderInit16((G722_1_16_encinst_t*)G722_1_16enc_inst[k]);
- } else {
- printf("\nError - G722.1 is only developed for 16kHz \n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_G722_1_24
- case webrtc::kDecoderG722_1_24:
- if (sampfreq == 16000) {
- ok = WebRtcG7221_CreateEnc24(&G722_1_24enc_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for G.722.1 instance\n");
- exit(0);
- }
- if (enc_frameSize == 320) {
- } else {
- printf("\nError: G722.1 only supports 20 ms!!\n\n");
- exit(0);
- }
- WebRtcG7221_EncoderInit24((G722_1_24_encinst_t*)G722_1_24enc_inst[k]);
- } else {
- printf("\nError - G722.1 is only developed for 16kHz \n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_G722_1_32
- case webrtc::kDecoderG722_1_32:
- if (sampfreq == 16000) {
- ok = WebRtcG7221_CreateEnc32(&G722_1_32enc_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for G.722.1 instance\n");
- exit(0);
- }
- if (enc_frameSize == 320) {
- } else {
- printf("\nError: G722.1 only supports 20 ms!!\n\n");
- exit(0);
- }
- WebRtcG7221_EncoderInit32((G722_1_32_encinst_t*)G722_1_32enc_inst[k]);
- } else {
- printf("\nError - G722.1 is only developed for 16kHz \n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_G722_1C_24
- case webrtc::kDecoderG722_1C_24:
- if (sampfreq == 32000) {
- ok = WebRtcG7221C_CreateEnc24(&G722_1C_24enc_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for G.722.1C instance\n");
- exit(0);
- }
- if (enc_frameSize == 640) {
- } else {
- printf("\nError: G722.1 C only supports 20 ms!!\n\n");
- exit(0);
- }
- WebRtcG7221C_EncoderInit24(
- (G722_1C_24_encinst_t*)G722_1C_24enc_inst[k]);
- } else {
- printf("\nError - G722.1 C is only developed for 32kHz \n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_G722_1C_32
- case webrtc::kDecoderG722_1C_32:
- if (sampfreq == 32000) {
- ok = WebRtcG7221C_CreateEnc32(&G722_1C_32enc_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for G.722.1C instance\n");
- exit(0);
- }
- if (enc_frameSize == 640) {
- } else {
- printf("\nError: G722.1 C only supports 20 ms!!\n\n");
- exit(0);
- }
- WebRtcG7221C_EncoderInit32(
- (G722_1C_32_encinst_t*)G722_1C_32enc_inst[k]);
- } else {
- printf("\nError - G722.1 C is only developed for 32kHz \n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_G722_1C_48
- case webrtc::kDecoderG722_1C_48:
- if (sampfreq == 32000) {
- ok = WebRtcG7221C_CreateEnc48(&G722_1C_48enc_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for G.722.1C instance\n");
- exit(0);
- }
- if (enc_frameSize == 640) {
- } else {
- printf("\nError: G722.1 C only supports 20 ms!!\n\n");
- exit(0);
- }
- WebRtcG7221C_EncoderInit48(
- (G722_1C_48_encinst_t*)G722_1C_48enc_inst[k]);
- } else {
- printf("\nError - G722.1 C is only developed for 32kHz \n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_G722
- case webrtc::NetEqDecoder::kDecoderG722:
- if (sampfreq == 16000) {
- if (enc_frameSize % 2 == 0) {
- } else {
- printf(
- "\nError - g722 frames must have an even number of "
- "enc_frameSize\n");
- exit(0);
- }
- WebRtcG722_CreateEncoder(&g722EncState[k]);
- WebRtcG722_EncoderInit(g722EncState[k]);
- } else {
- printf("\nError - g722 is only developed for 16kHz \n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_AMR
- case webrtc::kDecoderAMR:
- if (sampfreq == 8000) {
- ok = WebRtcAmr_CreateEnc(&AMRenc_inst[k]);
- if (ok != 0) {
- printf(
- "Error: Couldn't allocate memory for AMR encoding instance\n");
- exit(0);
- }
- if ((enc_frameSize == 160) || (enc_frameSize == 320) ||
- (enc_frameSize == 480)) {
- } else {
- printf("\nError - AMR must have a multiple of 160 enc_frameSize\n");
- exit(0);
- }
- WebRtcAmr_EncoderInit(AMRenc_inst[k], vad);
- WebRtcAmr_EncodeBitmode(AMRenc_inst[k], AMRBandwidthEfficient);
- AMR_bitrate = bitrate;
- } else {
- printf("\nError - AMR is only developed for 8kHz \n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_AMRWB
- case webrtc::kDecoderAMRWB:
- if (sampfreq == 16000) {
- ok = WebRtcAmrWb_CreateEnc(&AMRWBenc_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for AMRWB encoding "
- "instance\n");
- exit(0);
- }
- if (((enc_frameSize / 320) > 3) || ((enc_frameSize % 320) != 0)) {
- printf("\nError - AMRwb must have frameSize of 20, 40 or 60ms\n");
- exit(0);
- }
- WebRtcAmrWb_EncoderInit(AMRWBenc_inst[k], vad);
- if (bitrate == 7000) {
- AMRWB_bitrate = AMRWB_MODE_7k;
- } else if (bitrate == 9000) {
- AMRWB_bitrate = AMRWB_MODE_9k;
- } else if (bitrate == 12000) {
- AMRWB_bitrate = AMRWB_MODE_12k;
- } else if (bitrate == 14000) {
- AMRWB_bitrate = AMRWB_MODE_14k;
- } else if (bitrate == 16000) {
- AMRWB_bitrate = AMRWB_MODE_16k;
- } else if (bitrate == 18000) {
- AMRWB_bitrate = AMRWB_MODE_18k;
- } else if (bitrate == 20000) {
- AMRWB_bitrate = AMRWB_MODE_20k;
- } else if (bitrate == 23000) {
- AMRWB_bitrate = AMRWB_MODE_23k;
- } else if (bitrate == 24000) {
- AMRWB_bitrate = AMRWB_MODE_24k;
- }
- WebRtcAmrWb_EncodeBitmode(AMRWBenc_inst[k], AMRBandwidthEfficient);
-
- } else {
- printf("\nError - AMRwb is only developed for 16kHz \n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_ILBC
- case webrtc::NetEqDecoder::kDecoderILBC:
- if (sampfreq == 8000) {
- ok = WebRtcIlbcfix_EncoderCreate(&iLBCenc_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for iLBC encoding "
- "instance\n");
- exit(0);
- }
- if ((enc_frameSize == 160) || (enc_frameSize == 240) ||
- (enc_frameSize == 320) || (enc_frameSize == 480)) {
- } else {
- printf("\nError - iLBC only supports 160, 240, 320 and 480 "
- "enc_frameSize (20, 30, 40 and 60 ms)\n");
- exit(0);
- }
- if ((enc_frameSize == 160) || (enc_frameSize == 320)) {
- /* 20 ms version */
- WebRtcIlbcfix_EncoderInit(iLBCenc_inst[k], 20);
- } else {
- /* 30 ms version */
- WebRtcIlbcfix_EncoderInit(iLBCenc_inst[k], 30);
- }
- } else {
- printf("\nError - iLBC is only developed for 8kHz \n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_ISAC
- case webrtc::NetEqDecoder::kDecoderISAC:
- if (sampfreq == 16000) {
- ok = WebRtcIsac_Create(&ISAC_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for iSAC instance\n");
- exit(0);
- }
- if ((enc_frameSize == 480) || (enc_frameSize == 960)) {
- } else {
- printf("\nError - iSAC only supports frameSize (30 and 60 ms)\n");
- exit(0);
- }
- WebRtcIsac_EncoderInit(ISAC_inst[k], 1);
- if ((bitrate < 10000) || (bitrate > 32000)) {
- printf("\nError - iSAC bitrate has to be between 10000 and 32000 "
- "bps (not %i)\n",
- bitrate);
- exit(0);
- }
- WebRtcIsac_Control(ISAC_inst[k], bitrate,
- static_cast<int>(enc_frameSize >> 4));
- } else {
- printf("\nError - iSAC only supports 480 or 960 enc_frameSize (30 or "
- "60 ms)\n");
- exit(0);
- }
- break;
-#endif
-#ifdef NETEQ_ISACFIX_CODEC
- case webrtc::kDecoderISAC:
- if (sampfreq == 16000) {
- ok = WebRtcIsacfix_Create(&ISAC_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for iSAC instance\n");
- exit(0);
- }
- if ((enc_frameSize == 480) || (enc_frameSize == 960)) {
- } else {
- printf("\nError - iSAC only supports frameSize (30 and 60 ms)\n");
- exit(0);
- }
- WebRtcIsacfix_EncoderInit(ISAC_inst[k], 1);
- if ((bitrate < 10000) || (bitrate > 32000)) {
- printf("\nError - iSAC bitrate has to be between 10000 and 32000 "
- "bps (not %i)\n", bitrate);
- exit(0);
- }
- WebRtcIsacfix_Control(ISAC_inst[k], bitrate, enc_frameSize >> 4);
- } else {
- printf("\nError - iSAC only supports 480 or 960 enc_frameSize (30 or "
- "60 ms)\n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_ISAC_SWB
- case webrtc::NetEqDecoder::kDecoderISACswb:
- if (sampfreq == 32000) {
- ok = WebRtcIsac_Create(&ISACSWB_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for iSAC SWB instance\n");
- exit(0);
- }
- if (enc_frameSize == 960) {
- } else {
- printf("\nError - iSAC SWB only supports frameSize 30 ms\n");
- exit(0);
- }
- ok = WebRtcIsac_SetEncSampRate(ISACSWB_inst[k], 32000);
- if (ok != 0) {
- printf("Error: Couldn't set sample rate for iSAC SWB instance\n");
- exit(0);
- }
- WebRtcIsac_EncoderInit(ISACSWB_inst[k], 1);
- if ((bitrate < 32000) || (bitrate > 56000)) {
- printf("\nError - iSAC SWB bitrate has to be between 32000 and "
- "56000 bps (not %i)\n", bitrate);
- exit(0);
- }
- WebRtcIsac_Control(ISACSWB_inst[k], bitrate,
- static_cast<int>(enc_frameSize >> 5));
- } else {
- printf("\nError - iSAC SWB only supports 960 enc_frameSize (30 "
- "ms)\n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_GSMFR
- case webrtc::kDecoderGSMFR:
- if (sampfreq == 8000) {
- ok = WebRtcGSMFR_CreateEnc(&GSMFRenc_inst[k]);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for GSM FR encoding "
- "instance\n");
- exit(0);
- }
- if ((enc_frameSize == 160) || (enc_frameSize == 320) ||
- (enc_frameSize == 480)) {
- } else {
- printf("\nError - GSM FR must have a multiple of 160 "
- "enc_frameSize\n");
- exit(0);
- }
- WebRtcGSMFR_EncoderInit(GSMFRenc_inst[k], 0);
- } else {
- printf("\nError - GSM FR is only developed for 8kHz \n");
- exit(0);
- }
- break;
-#endif
-#ifdef CODEC_OPUS
- case webrtc::NetEqDecoder::kDecoderOpus:
- ok = WebRtcOpus_EncoderCreate(&opus_inst[k], 1, 0);
- if (ok != 0) {
- printf("Error: Couldn't allocate memory for Opus encoding "
- "instance\n");
- exit(0);
- }
- WebRtcOpus_EnableFec(opus_inst[k]);
- WebRtcOpus_SetPacketLossRate(opus_inst[k], 5);
- break;
-#endif
- default:
- printf("Error: unknown codec in call to NetEQTest_init_coders.\n");
- exit(0);
- break;
- }
- if (ok != 0) {
- return (ok);
- }
- } // end for
-
- return (0);
-}
-
-int NetEQTest_free_coders(webrtc::NetEqDecoder coder, size_t numChannels) {
- for (size_t k = 0; k < numChannels; k++) {
- WebRtcVad_Free(VAD_inst[k]);
-#if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \
- defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48))
- delete CNG_encoder[k];
- CNG_encoder[k] = nullptr;
-#endif
-
- switch (coder) {
-#ifdef CODEC_PCM16B
- case webrtc::NetEqDecoder::kDecoderPCM16B:
-#endif
-#ifdef CODEC_PCM16B_WB
- case webrtc::NetEqDecoder::kDecoderPCM16Bwb:
-#endif
-#ifdef CODEC_PCM16B_32KHZ
- case webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz:
-#endif
-#ifdef CODEC_PCM16B_48KHZ
- case webrtc::NetEqDecoder::kDecoderPCM16Bswb48kHz:
-#endif
-#ifdef CODEC_G711
- case webrtc::NetEqDecoder::kDecoderPCMu:
- case webrtc::NetEqDecoder::kDecoderPCMa:
-#endif
- // do nothing
- break;
-#ifdef CODEC_G729
- case webrtc::NetEqDecoder::kDecoderG729:
- WebRtcG729_FreeEnc(G729enc_inst[k]);
- break;
-#endif
-#ifdef CODEC_G729_1
- case webrtc::NetEqDecoder::kDecoderG729_1:
- WebRtcG7291_Free(G729_1_inst[k]);
- break;
-#endif
-
-#ifdef CODEC_G722_1_16
- case webrtc::NetEqDecoder::kDecoderG722_1_16:
- WebRtcG7221_FreeEnc16(G722_1_16enc_inst[k]);
- break;
-#endif
-#ifdef CODEC_G722_1_24
- case webrtc::NetEqDecoder::kDecoderG722_1_24:
- WebRtcG7221_FreeEnc24(G722_1_24enc_inst[k]);
- break;
-#endif
-#ifdef CODEC_G722_1_32
- case webrtc::NetEqDecoder::kDecoderG722_1_32:
- WebRtcG7221_FreeEnc32(G722_1_32enc_inst[k]);
- break;
-#endif
-#ifdef CODEC_G722_1C_24
- case webrtc::NetEqDecoder::kDecoderG722_1C_24:
- WebRtcG7221C_FreeEnc24(G722_1C_24enc_inst[k]);
- break;
-#endif
-#ifdef CODEC_G722_1C_32
- case webrtc::NetEqDecoder::kDecoderG722_1C_32:
- WebRtcG7221C_FreeEnc32(G722_1C_32enc_inst[k]);
- break;
-#endif
-#ifdef CODEC_G722_1C_48
- case webrtc::NetEqDecoder::kDecoderG722_1C_48:
- WebRtcG7221C_FreeEnc48(G722_1C_48enc_inst[k]);
- break;
-#endif
-#ifdef CODEC_G722
- case webrtc::NetEqDecoder::kDecoderG722:
- WebRtcG722_FreeEncoder(g722EncState[k]);
- break;
-#endif
-#ifdef CODEC_AMR
- case webrtc::NetEqDecoder::kDecoderAMR:
- WebRtcAmr_FreeEnc(AMRenc_inst[k]);
- break;
-#endif
-#ifdef CODEC_AMRWB
- case webrtc::NetEqDecoder::kDecoderAMRWB:
- WebRtcAmrWb_FreeEnc(AMRWBenc_inst[k]);
- break;
-#endif
-#ifdef CODEC_ILBC
- case webrtc::NetEqDecoder::kDecoderILBC:
- WebRtcIlbcfix_EncoderFree(iLBCenc_inst[k]);
- break;
-#endif
-#ifdef CODEC_ISAC
- case webrtc::NetEqDecoder::kDecoderISAC:
- WebRtcIsac_Free(ISAC_inst[k]);
- break;
-#endif
-#ifdef NETEQ_ISACFIX_CODEC
- case webrtc::NetEqDecoder::kDecoderISAC:
- WebRtcIsacfix_Free(ISAC_inst[k]);
- break;
-#endif
-#ifdef CODEC_ISAC_SWB
- case webrtc::NetEqDecoder::kDecoderISACswb:
- WebRtcIsac_Free(ISACSWB_inst[k]);
- break;
-#endif
-#ifdef CODEC_GSMFR
- case webrtc::NetEqDecoder::kDecoderGSMFR:
- WebRtcGSMFR_FreeEnc(GSMFRenc_inst[k]);
- break;
-#endif
-#ifdef CODEC_OPUS
- case webrtc::NetEqDecoder::kDecoderOpus:
- WebRtcOpus_EncoderFree(opus_inst[k]);
- break;
-#endif
- default:
- printf("Error: unknown codec in call to NetEQTest_init_coders.\n");
- exit(0);
- break;
- }
- }
-
- return (0);
-}
-
-size_t NetEQTest_encode(webrtc::NetEqDecoder coder,
- int16_t* indata,
- size_t frameLen,
- unsigned char* encoded,
- int sampleRate,
- int* vad,
- int useVAD,
- int bitrate,
- size_t numChannels) {
- size_t cdlen = 0;
- int16_t* tempdata;
- static bool first_cng = true;
- size_t tempLen;
- *vad = 1;
-
- // check VAD first
- if (useVAD) {
- *vad = 0;
-
- const size_t sampleRate_10 = static_cast<size_t>(10 * sampleRate / 1000);
- const size_t sampleRate_20 = static_cast<size_t>(20 * sampleRate / 1000);
- const size_t sampleRate_30 = static_cast<size_t>(30 * sampleRate / 1000);
- for (size_t k = 0; k < numChannels; k++) {
- tempLen = frameLen;
- tempdata = &indata[k * frameLen];
- int localVad = 0;
- /* Partition the signal and test each chunk for VAD.
- All chunks must be VAD=0 to produce a total VAD=0. */
- while (tempLen >= sampleRate_10) {
- if ((tempLen % sampleRate_30) == 0) { // tempLen is multiple of 30ms
- localVad |= WebRtcVad_Process(VAD_inst[k], sampleRate, tempdata,
- sampleRate_30);
- tempdata += sampleRate_30;
- tempLen -= sampleRate_30;
- } else if (tempLen >= sampleRate_20) { // tempLen >= 20ms
- localVad |= WebRtcVad_Process(VAD_inst[k], sampleRate, tempdata,
- sampleRate_20);
- tempdata += sampleRate_20;
- tempLen -= sampleRate_20;
- } else { // use 10ms
- localVad |= WebRtcVad_Process(VAD_inst[k], sampleRate, tempdata,
- sampleRate_10);
- tempdata += sampleRate_10;
- tempLen -= sampleRate_10;
- }
- }
-
- // aggregate all VAD decisions over all channels
- *vad |= localVad;
- }
-
- if (!*vad) {
- // all channels are silent
- rtc::Buffer workaround;
- cdlen = 0;
- for (size_t k = 0; k < numChannels; k++) {
- workaround.Clear();
- tempLen = CNG_encoder[k]->Encode(
- rtc::ArrayView<const int16_t>(
- &indata[k * frameLen],
- (frameLen <= 640 ? frameLen : 640) /* max 640 */),
- first_cng,
- &workaround);
- memcpy(encoded, workaround.data(), tempLen);
- encoded += tempLen;
- cdlen += tempLen;
- }
- *vad = 0;
- first_cng = false;
- return (cdlen);
- }
- }
-
- // loop over all channels
- size_t totalLen = 0;
-
- for (size_t k = 0; k < numChannels; k++) {
- /* Encode with the selected coder type */
- if (coder == webrtc::NetEqDecoder::kDecoderPCMu) { /*g711 u-law */
-#ifdef CODEC_G711
- cdlen = WebRtcG711_EncodeU(indata, frameLen, encoded);
-#endif
- } else if (coder == webrtc::NetEqDecoder::kDecoderPCMa) { /*g711 A-law */
-#ifdef CODEC_G711
- cdlen = WebRtcG711_EncodeA(indata, frameLen, encoded);
- }
-#endif
-#ifdef CODEC_PCM16B
- else if ((coder == webrtc::NetEqDecoder::kDecoderPCM16B) ||
- (coder == webrtc::NetEqDecoder::kDecoderPCM16Bwb) ||
- (coder == webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz) ||
- (coder == webrtc::NetEqDecoder::
- kDecoderPCM16Bswb48kHz)) { /*pcm16b (8kHz, 16kHz,
- 32kHz or 48kHz) */
- cdlen = WebRtcPcm16b_Encode(indata, frameLen, encoded);
- }
-#endif
-#ifdef CODEC_G722
- else if (coder == webrtc::NetEqDecoder::kDecoderG722) { /*g722 */
- cdlen = WebRtcG722_Encode(g722EncState[k], indata, frameLen, encoded);
- assert(cdlen == frameLen >> 1);
- }
-#endif
-#ifdef CODEC_ILBC
- else if (coder == webrtc::NetEqDecoder::kDecoderILBC) { /*iLBC */
- cdlen = static_cast<size_t>(std::max(
- WebRtcIlbcfix_Encode(iLBCenc_inst[k], indata, frameLen, encoded), 0));
- }
-#endif
-#if (defined(CODEC_ISAC) || \
- defined(NETEQ_ISACFIX_CODEC)) // TODO(hlundin): remove all
- // NETEQ_ISACFIX_CODEC
- else if (coder == webrtc::NetEqDecoder::kDecoderISAC) { /*iSAC */
- int noOfCalls = 0;
- int res = 0;
- while (res <= 0) {
-#ifdef CODEC_ISAC /* floating point */
- res =
- WebRtcIsac_Encode(ISAC_inst[k], &indata[noOfCalls * 160], encoded);
-#else /* fixed point */
- res = WebRtcIsacfix_Encode(ISAC_inst[k], &indata[noOfCalls * 160],
- encoded);
-#endif
- noOfCalls++;
- }
- cdlen = static_cast<size_t>(res);
- }
-#endif
-#ifdef CODEC_ISAC_SWB
- else if (coder == webrtc::NetEqDecoder::kDecoderISACswb) { /* iSAC SWB */
- int noOfCalls = 0;
- int res = 0;
- while (res <= 0) {
- res = WebRtcIsac_Encode(ISACSWB_inst[k], &indata[noOfCalls * 320],
- encoded);
- noOfCalls++;
- }
- cdlen = static_cast<size_t>(res);
- }
-#endif
-#ifdef CODEC_OPUS
- cdlen = WebRtcOpus_Encode(opus_inst[k], indata, frameLen, kRtpDataSize - 12,
- encoded);
- RTC_CHECK_GT(cdlen, 0);
-#endif
- indata += frameLen;
- encoded += cdlen;
- totalLen += cdlen;
-
- } // end for
-
- first_cng = true;
- return (totalLen);
-}
-
-void makeRTPheader(unsigned char* rtp_data,
- int payloadType,
- int seqNo,
- uint32_t timestamp,
- uint32_t ssrc) {
- rtp_data[0] = 0x80;
- rtp_data[1] = payloadType & 0xFF;
- rtp_data[2] = (seqNo >> 8) & 0xFF;
- rtp_data[3] = seqNo & 0xFF;
- rtp_data[4] = timestamp >> 24;
- rtp_data[5] = (timestamp >> 16) & 0xFF;
- rtp_data[6] = (timestamp >> 8) & 0xFF;
- rtp_data[7] = timestamp & 0xFF;
- rtp_data[8] = ssrc >> 24;
- rtp_data[9] = (ssrc >> 16) & 0xFF;
- rtp_data[10] = (ssrc >> 8) & 0xFF;
- rtp_data[11] = ssrc & 0xFF;
-}
-
-int makeRedundantHeader(unsigned char* rtp_data,
- int* payloadType,
- int numPayloads,
- uint32_t* timestamp,
- uint16_t* blockLen,
- int seqNo,
- uint32_t ssrc) {
- int i;
- unsigned char* rtpPointer;
- uint16_t offset;
-
- /* first create "standard" RTP header */
- makeRTPheader(rtp_data, NETEQ_CODEC_RED_PT, seqNo, timestamp[numPayloads - 1],
- ssrc);
-
- rtpPointer = &rtp_data[12];
-
- /* add one sub-header for each redundant payload (not the primary) */
- for (i = 0; i < numPayloads - 1; i++) {
- if (blockLen[i] > 0) {
- offset = static_cast<uint16_t>(timestamp[numPayloads - 1] - timestamp[i]);
-
- // Byte |0| |1 2 | 3 |
- // Bit |0|1234567|01234567012345|6701234567|
- // |F|payload| timestamp | block |
- // | | type | offset | length |
- rtpPointer[0] = (payloadType[i] & 0x7F) | 0x80;
- rtpPointer[1] = (offset >> 6) & 0xFF;
- rtpPointer[2] = ((offset & 0x3F) << 2) | ((blockLen[i] >> 8) & 0x03);
- rtpPointer[3] = blockLen[i] & 0xFF;
-
- rtpPointer += 4;
- }
- }
-
- // Bit |0|1234567|
- // |0|payload|
- // | | type |
- rtpPointer[0] = payloadType[numPayloads - 1] & 0x7F;
- ++rtpPointer;
-
- return rtpPointer - rtp_data; // length of header in bytes
-}
-
-size_t makeDTMFpayload(unsigned char* payload_data,
- int Event,
- int End,
- int Volume,
- int Duration) {
- unsigned char E, R, V;
- R = 0;
- V = (unsigned char)Volume;
- if (End == 0) {
- E = 0x00;
- } else {
- E = 0x80;
- }
- payload_data[0] = (unsigned char)Event;
- payload_data[1] = (unsigned char)(E | R | V);
- // Duration equals 8 times time_ms, default is 8000 Hz.
- payload_data[2] = (unsigned char)((Duration >> 8) & 0xFF);
- payload_data[3] = (unsigned char)(Duration & 0xFF);
- return (4);
-}
-
-void stereoDeInterleave(int16_t* audioSamples, size_t numSamples) {
- int16_t* tempVec;
- int16_t* readPtr, *writeL, *writeR;
-
- if (numSamples == 0)
- return;
-
- tempVec = (int16_t*)malloc(sizeof(int16_t) * numSamples);
- if (tempVec == NULL) {
- printf("Error allocating memory\n");
- exit(0);
- }
-
- memcpy(tempVec, audioSamples, numSamples * sizeof(int16_t));
-
- writeL = audioSamples;
- writeR = &audioSamples[numSamples / 2];
- readPtr = tempVec;
-
- for (size_t k = 0; k < numSamples; k += 2) {
- *writeL = *readPtr;
- readPtr++;
- *writeR = *readPtr;
- readPtr++;
- writeL++;
- writeR++;
- }
-
- free(tempVec);
-}
-
-void stereoInterleave(unsigned char* data, size_t dataLen, size_t stride) {
- unsigned char* ptrL, *ptrR;
- unsigned char temp[10];
-
- if (stride > 10) {
- exit(0);
- }
-
- if (dataLen % 1 != 0) {
- // must be even number of samples
- printf("Error: cannot interleave odd sample number\n");
- exit(0);
- }
-
- ptrL = data + stride;
- ptrR = &data[dataLen / 2];
-
- while (ptrL < ptrR) {
- // copy from right pointer to temp
- memcpy(temp, ptrR, stride);
-
- // shift data between pointers
- memmove(ptrL + stride, ptrL, ptrR - ptrL);
-
- // copy from temp to left pointer
- memcpy(ptrL, temp, stride);
-
- // advance pointers
- ptrL += stride * 2;
- ptrR += stride;
- }
-}
diff --git a/modules/audio_coding/neteq/tools/input_audio_file.cc b/modules/audio_coding/neteq/tools/input_audio_file.cc
index 8c8b72c..31ebf98 100644
--- a/modules/audio_coding/neteq/tools/input_audio_file.cc
+++ b/modules/audio_coding/neteq/tools/input_audio_file.cc
@@ -15,7 +15,8 @@
namespace webrtc {
namespace test {
-InputAudioFile::InputAudioFile(const std::string file_name) {
+InputAudioFile::InputAudioFile(const std::string file_name, bool loop_at_end)
+ : loop_at_end_(loop_at_end) {
fp_ = fopen(file_name.c_str(), "rb");
}
@@ -27,6 +28,9 @@
}
size_t samples_read = fread(destination, sizeof(int16_t), samples, fp_);
if (samples_read < samples) {
+ if (!loop_at_end_) {
+ return false;
+ }
// Rewind and read the missing samples.
rewind(fp_);
size_t missing_samples = samples - samples_read;
@@ -54,7 +58,11 @@
long new_pos = current_pos + sizeof(int16_t) * samples; // Samples to bytes.
RTC_CHECK_GE(new_pos, 0)
<< "Trying to move to before the beginning of the file";
- new_pos = new_pos % file_size; // Wrap around the end of the file.
+ if (loop_at_end_) {
+ new_pos = new_pos % file_size; // Wrap around the end of the file.
+ } else {
+ new_pos = new_pos > file_size ? file_size : new_pos; // Don't loop.
+ }
// Move to new position relative to the beginning of the file.
RTC_CHECK_EQ(0, fseek(fp_, new_pos, SEEK_SET));
return true;
diff --git a/modules/audio_coding/neteq/tools/input_audio_file.h b/modules/audio_coding/neteq/tools/input_audio_file.h
index 22675d8..6bfa369 100644
--- a/modules/audio_coding/neteq/tools/input_audio_file.h
+++ b/modules/audio_coding/neteq/tools/input_audio_file.h
@@ -24,7 +24,7 @@
// Class for handling a looping input audio file.
class InputAudioFile {
public:
- explicit InputAudioFile(const std::string file_name);
+ explicit InputAudioFile(const std::string file_name, bool loop_at_end = true);
virtual ~InputAudioFile();
@@ -50,6 +50,7 @@
private:
FILE* fp_;
+ const bool loop_at_end_;
RTC_DISALLOW_COPY_AND_ASSIGN(InputAudioFile);
};
diff --git a/modules/audio_coding/neteq/tools/rtp_encode.cc b/modules/audio_coding/neteq/tools/rtp_encode.cc
new file mode 100644
index 0000000..ca475da
--- /dev/null
+++ b/modules/audio_coding/neteq/tools/rtp_encode.cc
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdio.h>
+
+#ifdef WIN32
+#include <winsock2.h>
+#endif
+#ifdef WEBRTC_LINUX
+#include <netinet/in.h>
+#endif
+
+#include <iostream>
+#include <map>
+#include <string>
+
+#include "api/audio_codecs/L16/audio_encoder_L16.h"
+#include "api/audio_codecs/g711/audio_encoder_g711.h"
+#include "api/audio_codecs/g722/audio_encoder_g722.h"
+#include "api/audio_codecs/ilbc/audio_encoder_ilbc.h"
+#include "api/audio_codecs/isac/audio_encoder_isac.h"
+#include "api/audio_codecs/opus/audio_encoder_opus.h"
+#include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
+#include "modules/audio_coding/include/audio_coding_module.h"
+#include "modules/audio_coding/neteq/tools/input_audio_file.h"
+#include "rtc_base/flags.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/ptr_util.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+namespace test {
+namespace {
+
+// Define command line flags.
+DEFINE_bool(list_codecs, false, "Enumerate all codecs");
+DEFINE_string(codec, "opus", "Codec to use");
+DEFINE_int(frame_len, 0, "Frame length in ms; 0 indicates codec default value");
+DEFINE_int(bitrate, 0, "Bitrate in kbps; 0 indicates codec default value");
+DEFINE_int(payload_type,
+ -1,
+ "RTP payload type; -1 indicates codec default value");
+DEFINE_int(cng_payload_type,
+ -1,
+ "RTP payload type for CNG; -1 indicates default value");
+DEFINE_int(ssrc, 0, "SSRC to write to the RTP header");
+DEFINE_bool(dtx, false, "Use DTX/CNG");
+DEFINE_int(sample_rate, 48000, "Sample rate of the input file");
+DEFINE_bool(help, false, "Print this message");
+
+// Add new codecs here, and to the map below.
+enum class CodecType {
+ kOpus,
+ kPcmU,
+ kPcmA,
+ kG722,
+ kPcm16b8,
+ kPcm16b16,
+ kPcm16b32,
+ kPcm16b48,
+ kIlbc,
+ kIsac
+};
+
+struct CodecTypeAndInfo {
+ CodecType type;
+ int default_payload_type;
+ bool internal_dtx;
+};
+
+// List all supported codecs here. This map defines the command-line parameter
+// value (the key string) for selecting each codec, together with information
+// whether it is using internal or external DTX/CNG.
+const std::map<std::string, CodecTypeAndInfo>& CodecList() {
+ static const auto* const codec_list =
+ new std::map<std::string, CodecTypeAndInfo>{
+ {"opus", {CodecType::kOpus, 111, true}},
+ {"pcmu", {CodecType::kPcmU, 0, false}},
+ {"pcma", {CodecType::kPcmA, 8, false}},
+ {"g722", {CodecType::kG722, 9, false}},
+ {"pcm16b_8", {CodecType::kPcm16b8, 93, false}},
+ {"pcm16b_16", {CodecType::kPcm16b16, 94, false}},
+ {"pcm16b_32", {CodecType::kPcm16b32, 95, false}},
+ {"pcm16b_48", {CodecType::kPcm16b48, 96, false}},
+ {"ilbc", {CodecType::kIlbc, 102, false}},
+ {"isac", {CodecType::kIsac, 103, false}}};
+ return *codec_list;
+}
+
+// This class will receive callbacks from ACM when a packet is ready, and write
+// it to the output file.
+class Packetizer : public AudioPacketizationCallback {
+ public:
+ Packetizer(FILE* out_file, uint32_t ssrc, int timestamp_rate_hz)
+ : out_file_(out_file),
+ ssrc_(ssrc),
+ timestamp_rate_hz_(timestamp_rate_hz) {}
+
+ int32_t SendData(FrameType frame_type,
+ uint8_t payload_type,
+ uint32_t timestamp,
+ const uint8_t* payload_data,
+ size_t payload_len_bytes,
+ const RTPFragmentationHeader* fragmentation) override {
+ RTC_CHECK(!fragmentation);
+ RTC_DCHECK_GT(payload_len_bytes, 0);
+
+ constexpr size_t kRtpHeaderLength = 12;
+ constexpr size_t kRtpDumpHeaderLength = 8;
+ const uint16_t length = htons(rtc::checked_cast<uint16_t>(
+ kRtpHeaderLength + kRtpDumpHeaderLength + payload_len_bytes));
+ const uint16_t plen = htons(
+ rtc::checked_cast<uint16_t>(kRtpHeaderLength + payload_len_bytes));
+ const uint32_t offset = htonl(timestamp / (timestamp_rate_hz_ / 1000));
+ RTC_CHECK_EQ(fwrite(&length, sizeof(uint16_t), 1, out_file_), 1);
+ RTC_CHECK_EQ(fwrite(&plen, sizeof(uint16_t), 1, out_file_), 1);
+ RTC_CHECK_EQ(fwrite(&offset, sizeof(uint32_t), 1, out_file_), 1);
+
+ const uint8_t rtp_header[] = {0x80,
+ static_cast<uint8_t>(payload_type & 0x7F),
+ static_cast<uint8_t>(sequence_number_ >> 8),
+ static_cast<uint8_t>(sequence_number_),
+ static_cast<uint8_t>(timestamp >> 24),
+ static_cast<uint8_t>(timestamp >> 16),
+ static_cast<uint8_t>(timestamp >> 8),
+ static_cast<uint8_t>(timestamp),
+ static_cast<uint8_t>(ssrc_ >> 24),
+ static_cast<uint8_t>(ssrc_ >> 16),
+ static_cast<uint8_t>(ssrc_ >> 8),
+ static_cast<uint8_t>(ssrc_)};
+ static_assert(sizeof(rtp_header) == kRtpHeaderLength, "");
+ RTC_CHECK_EQ(
+ fwrite(rtp_header, sizeof(uint8_t), kRtpHeaderLength, out_file_),
+ kRtpHeaderLength);
+ ++sequence_number_; // Intended to wrap on overflow.
+
+ RTC_CHECK_EQ(
+ fwrite(payload_data, sizeof(uint8_t), payload_len_bytes, out_file_),
+ payload_len_bytes);
+
+ return 0;
+ }
+
+ private:
+ FILE* const out_file_;
+ const uint32_t ssrc_;
+ const int timestamp_rate_hz_;
+ uint16_t sequence_number_ = 0;
+};
+
+void SetFrameLenIfFlagIsPositive(int* config_frame_len) {
+ if (FLAG_frame_len > 0) {
+ *config_frame_len = FLAG_frame_len;
+ }
+}
+
+AudioEncoderL16::Config Pcm16bConfig(CodecType codec_type) {
+ AudioEncoderL16::Config config;
+ SetFrameLenIfFlagIsPositive(&config.frame_size_ms);
+ switch (codec_type) {
+ case CodecType::kPcm16b8:
+ config.sample_rate_hz = 8000;
+ return config;
+ case CodecType::kPcm16b16:
+ config.sample_rate_hz = 16000;
+ return config;
+ case CodecType::kPcm16b32:
+ config.sample_rate_hz = 32000;
+ return config;
+ case CodecType::kPcm16b48:
+ config.sample_rate_hz = 48000;
+ return config;
+ default:
+ RTC_NOTREACHED();
+ return config;
+ }
+}
+
+std::unique_ptr<AudioEncoder> CreateEncoder(CodecType codec_type,
+ int payload_type) {
+ switch (codec_type) {
+ case CodecType::kOpus: {
+ AudioEncoderOpusConfig config;
+ if (FLAG_bitrate > 0) {
+ config.bitrate_bps = FLAG_bitrate;
+ }
+ config.dtx_enabled = FLAG_dtx;
+ SetFrameLenIfFlagIsPositive(&config.frame_size_ms);
+ RTC_CHECK(config.IsOk());
+ return AudioEncoderOpus::MakeAudioEncoder(config, payload_type);
+ }
+
+ case CodecType::kPcmU:
+ case CodecType::kPcmA: {
+ AudioEncoderG711::Config config;
+ SetFrameLenIfFlagIsPositive(&config.frame_size_ms);
+ config.type = codec_type == CodecType::kPcmU
+ ? AudioEncoderG711::Config::Type::kPcmU
+ : AudioEncoderG711::Config::Type::kPcmA;
+ RTC_CHECK(config.IsOk());
+ return AudioEncoderG711::MakeAudioEncoder(config, payload_type);
+ }
+
+ case CodecType::kG722: {
+ AudioEncoderG722Config config;
+ SetFrameLenIfFlagIsPositive(&config.frame_size_ms);
+ RTC_CHECK(config.IsOk());
+ return AudioEncoderG722::MakeAudioEncoder(config, payload_type);
+ }
+
+ case CodecType::kPcm16b8:
+ case CodecType::kPcm16b16:
+ case CodecType::kPcm16b32:
+ case CodecType::kPcm16b48: {
+ return AudioEncoderL16::MakeAudioEncoder(Pcm16bConfig(codec_type),
+ payload_type);
+ }
+
+ case CodecType::kIlbc: {
+ AudioEncoderIlbcConfig config;
+ SetFrameLenIfFlagIsPositive(&config.frame_size_ms);
+ RTC_CHECK(config.IsOk());
+ return AudioEncoderIlbc::MakeAudioEncoder(config, payload_type);
+ }
+
+ case CodecType::kIsac: {
+ AudioEncoderIsac::Config config;
+ SetFrameLenIfFlagIsPositive(&config.frame_size_ms);
+ RTC_CHECK(config.IsOk());
+ return AudioEncoderIsac::MakeAudioEncoder(config, payload_type);
+ }
+ }
+ RTC_NOTREACHED();
+ return nullptr;
+}
+
+AudioEncoderCng::Config GetCngConfig(int sample_rate_hz) {
+ AudioEncoderCng::Config cng_config;
+ const auto default_payload_type = [&] {
+ switch (sample_rate_hz) {
+ case 8000: return 13;
+ case 16000: return 98;
+ case 32000: return 99;
+ case 48000: return 100;
+ default: RTC_NOTREACHED();
+ }
+ return 0;
+ };
+ cng_config.payload_type = FLAG_cng_payload_type != -1
+ ? FLAG_cng_payload_type
+ : default_payload_type();
+ return cng_config;
+}
+
+int RunRtpEncode(int argc, char* argv[]) {
+ const std::string program_name = argv[0];
+ const std::string usage =
+ "Tool for generating an RTP dump file from audio input.\n"
+ "Run " +
+ program_name +
+ " --help for usage.\n"
+ "Example usage:\n" +
+ program_name + " input.pcm output.rtp --codec=[codec] " +
+ "--frame_len=[frame_len] --bitrate=[bitrate]\n\n";
+ if (rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, true) || FLAG_help ||
+ (!FLAG_list_codecs && argc != 3)) {
+ printf("%s", usage.c_str());
+ if (FLAG_help) {
+ rtc::FlagList::Print(nullptr, false);
+ return 0;
+ }
+ return 1;
+ }
+
+ if (FLAG_list_codecs) {
+ printf("The following arguments are valid --codec parameters:\n");
+ for (const auto& c : CodecList()) {
+ printf(" %s\n", c.first.c_str());
+ }
+ return 0;
+ }
+
+ const auto codec_it = CodecList().find(FLAG_codec);
+ if (codec_it == CodecList().end()) {
+ printf("%s is not a valid codec name.\n", FLAG_codec);
+ printf("Use argument --list_codecs to see all valid codec names.\n");
+ return 1;
+ }
+
+ // Create the codec.
+ const int payload_type = FLAG_payload_type == -1
+ ? codec_it->second.default_payload_type
+ : FLAG_payload_type;
+ std::unique_ptr<AudioEncoder> codec =
+ CreateEncoder(codec_it->second.type, payload_type);
+
+ // Create an external VAD/CNG encoder if needed.
+ if (FLAG_dtx && codec_it->second.internal_dtx) {
+ AudioEncoderCng::Config cng_config = GetCngConfig(codec->SampleRateHz());
+ RTC_DCHECK(codec);
+ cng_config.speech_encoder = std::move(codec);
+ codec = rtc::MakeUnique<AudioEncoderCng>(std::move(cng_config));
+ }
+ RTC_DCHECK(codec);
+
+ // Set up ACM.
+ const int timestamp_rate_hz = codec->RtpTimestampRateHz();
+ AudioCodingModule::Config config;
+ std::unique_ptr<AudioCodingModule> acm(AudioCodingModule::Create(config));
+ acm->SetEncoder(std::move(codec));
+
+ // Open files.
+ printf("Input file: %s\n", argv[1]);
+ InputAudioFile input_file(argv[1], false); // Open input in non-looping mode.
+ FILE* out_file = fopen(argv[2], "wb");
+ RTC_CHECK(out_file) << "Could not open file " << argv[2] << " for writing";
+ printf("Output file: %s\n", argv[2]);
+ fprintf(out_file, "#!rtpplay1.0 \n"); //,
+ // Write 3 32-bit values followed by 2 16-bit values, all set to 0. This means
+ // a total of 16 bytes.
+ const uint8_t file_header[16] = {0};
+ RTC_CHECK_EQ(fwrite(file_header, sizeof(file_header), 1, out_file), 1);
+
+ // Create and register the packetizer, which will write the packets to file.
+ Packetizer packetizer(out_file, FLAG_ssrc, timestamp_rate_hz);
+ RTC_DCHECK_EQ(acm->RegisterTransportCallback(&packetizer), 0);
+
+ AudioFrame audio_frame;
+ audio_frame.samples_per_channel_ = FLAG_sample_rate / 100; // 10 ms
+ audio_frame.sample_rate_hz_ = FLAG_sample_rate;
+ audio_frame.num_channels_ = 1;
+
+ while (input_file.Read(audio_frame.samples_per_channel_,
+ audio_frame.mutable_data())) {
+ RTC_CHECK_GE(acm->Add10MsData(audio_frame), 0);
+ audio_frame.timestamp_ += audio_frame.samples_per_channel_;
+ }
+
+ return 0;
+}
+
+} // namespace
+} // namespace test
+} // namespace webrtc
+
+int main(int argc, char* argv[]) {
+ return webrtc::test::RunRtpEncode(argc, argv);
+}