You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rtpengine/t/test-transcode.c

1724 lines
64 KiB

#include "codec.h"
#include "call.h"
#include "call_interfaces.h"
#include "log.h"
#include "main.h"
#include "ssrc.h"
#include "helpers.h"
int _log_facility_rtcp;
int _log_facility_cdr;
int _log_facility_dtmf;
struct rtpengine_config rtpe_config;
struct rtpengine_config initial_rtpe_config;
struct poller *rtpe_poller;
struct poller_map *rtpe_poller_map;
GString *dtmf_logs;
GQueue rtpe_control_ng = G_QUEUE_INIT;
static str *sdup(char *s) {
str r = STR_INIT(s);
return str_dup(&r);
}
static void queue_dump(GString *s, GQueue *q) {
for (GList *l = q->head; l; l = l->next) {
if (s->len)
g_string_append(s, " ");
struct rtp_payload_type *pt = l->data;
g_string_append_printf(s, "%i/%s", pt->payload_type, pt->encoding_with_params.s);
if (pt->format_parameters.len)
g_string_append_printf(s, "/%s", pt->format_parameters.s);
}
}
// global variables used by tests
static GHashTable *rtp_ts_ht;
static GHashTable *rtp_seq_ht;
static uint32_t ssrc_A;
static uint32_t ssrc_B;
static struct call call;
static struct sdp_ng_flags flags;
static struct call_media *media_A;
static struct call_media *media_B;
struct call_monologue *ml_A;
struct call_monologue *ml_B;
struct stream_params rtp_types_sp;
#define start() __start(__FILE__, __LINE__)
static void __cleanup(void) {
if (flags.codec_except)
g_hash_table_destroy(flags.codec_except);
if (flags.codec_set)
g_hash_table_destroy(flags.codec_set);
if (flags.sdes_no)
g_hash_table_destroy(flags.sdes_no);
g_queue_clear_full(&flags.codec_offer, free);
g_queue_clear_full(&flags.codec_transcode, free);
g_queue_clear_full(&flags.codec_strip, free);
g_queue_clear_full(&flags.codec_accept, free);
g_queue_clear_full(&flags.codec_consume, free);
g_queue_clear_full(&flags.codec_mask, free);
g_queue_clear(&call.monologues);
codec_store_cleanup(&rtp_types_sp.codecs);
memset(&flags, 0, sizeof(flags));
}
static void __init(void) {
__cleanup();
codec_store_init(&rtp_types_sp.codecs, NULL);
rtp_types_sp.rtp_endpoint.port = 9;
flags.codec_except = g_hash_table_new_full(str_case_hash, str_case_equal, free, NULL);
flags.codec_set = g_hash_table_new_full(str_case_hash, str_case_equal, free, free);
}
static struct packet_stream *ps_new(struct call *c) {
struct packet_stream *ps = malloc(sizeof(*ps));
assert(ps != NULL);
memset(ps, 0, sizeof(*ps));
ps->endpoint.port = 12345;
return ps;
}
static void __start(const char *file, int line) {
printf("running test %s:%i\n", file, line);
rtp_ts_ht = g_hash_table_new(g_direct_hash, g_direct_equal);
rtp_seq_ht = g_hash_table_new(g_direct_hash, g_direct_equal);
ssrc_A = 1234;
ssrc_B = 2345;
ZERO(call);
obj_hold(&call);
call.tags = g_hash_table_new(g_str_hash, g_str_equal);
str_init(&call.callid, "test-call");
bencode_buffer_init(&call.buffer);
ml_A = __monologue_create(&call);
ml_B = __monologue_create(&call);
media_A = call_media_new(&call); // originator
media_B = call_media_new(&call); // output destination
g_queue_push_tail(&media_A->streams, ps_new(&call));
g_queue_push_tail(&media_B->streams, ps_new(&call));
str_init(&ml_A->tag, "tag_A");
media_A->monologue = ml_A;
media_A->protocol = &transport_protocols[PROTO_RTP_AVP];
str_init(&ml_B->tag, "tag_B");
media_B->monologue = ml_B;
media_B->protocol = &transport_protocols[PROTO_RTP_AVP];
__init();
}
#define transcode(codec) g_queue_push_tail(&flags.codec_transcode, sdup(#codec))
#define c_accept(codec) g_queue_push_tail(&flags.codec_accept, sdup(#codec))
#define c_consume(codec) g_queue_push_tail(&flags.codec_consume, sdup(#codec))
#define c_mask(codec) g_queue_push_tail(&flags.codec_mask, sdup(#codec))
#ifdef WITH_AMR_TESTS
static void codec_set(char *c) {
// from call_ng_flags_str_ht_split
c = strdup(c);
str s = STR_INIT(c);
str splitter = s;
while (1) {
g_hash_table_replace(flags.codec_set, str_dup(&splitter), str_dup(&s));
char *cp = memrchr(splitter.s, '/', splitter.len);
if (!cp)
break;
splitter.len = cp - splitter.s;
}
free(c);
}
#endif
//static void __ht_set(GHashTable *h, char *x) {
// str *d = sdup(x);
// g_hash_table_insert(h, d, d);
//}
//#define ht_set(ht, s) __ht_set(flags.ht, #s)
#define sdp_pt_fmt_ch(num, codec, clockrate, channels, fmt) \
__sdp_pt_fmt(num, (str) STR_CONST_INIT(#codec), clockrate, channels, (str) STR_CONST_INIT(#codec "/" #clockrate), \
(str) STR_CONST_INIT(#codec "/" #clockrate "/" #channels), (str) STR_CONST_INIT(fmt))
#define sdp_pt_fmt(num, codec, clockrate, fmt) sdp_pt_fmt_ch(num, codec, clockrate, 1, fmt)
#define sdp_pt_fmt_s(num, codec, clockrate, fmt) sdp_pt_fmt_ch(num, codec, clockrate, 2, fmt)
static void __sdp_pt_fmt(int num, str codec, int clockrate, int channels, str full_codec, str full_full, str fmt) {
str *fmtdup = str_dup(&fmt);
struct rtp_payload_type pt = (struct rtp_payload_type) {
.payload_type = num,
.encoding_with_params = full_codec,
.encoding_with_full_params = full_full,
.encoding = codec,
.clock_rate = clockrate,
.encoding_parameters = STR_CONST_INIT(""),
.channels = channels,
.format_parameters = *fmtdup,
.codec_opts = STR_NULL,
.rtcp_fb = G_QUEUE_INIT,
.ptime = 0,
.bitrate = 0,
.codec_def = NULL,
};
codec_store_add_raw(&rtp_types_sp.codecs, rtp_payload_type_dup(&pt));
free(fmtdup);
}
#define sdp_pt(num, codec, clockrate) sdp_pt_fmt(num, codec, clockrate, "")
#define sdp_pt_s(num, codec, clockrate) sdp_pt_fmt_s(num, codec, clockrate, "")
static void offer(void) {
printf("offer\n");
flags.opmode = OP_OFFER;
codecs_offer_answer(media_B, media_A, &rtp_types_sp, &flags);
__init();
}
static void answer(void) {
printf("answer\n");
flags.opmode = OP_ANSWER;
codecs_offer_answer(media_A, media_B, &rtp_types_sp, &flags);
__init();
}
#define expect(side, exp_str) \
__expect(__FILE__, __LINE__, &media_ ## side->codecs.codec_prefs, exp_str)
static void __expect(const char *file, int line, GQueue *dumper, const char *codecs) {
printf("running test %s:%i\n", file, line);
GString *s = g_string_new("");
queue_dump(s, dumper);
if (strcmp(s->str, codecs) != 0) {
printf("test failed: %s:%i\n", file, line);
printf("expected: %s\n", codecs);
printf("received: %s\n", s->str);
abort();
}
printf("test ok: %s:%i\n\n", file, line);
g_string_free(s, TRUE);
}
#ifdef WITH_AMR_TESTS
#define check_encoder(side, otherside, in_pt, out_pt, out_bitrate) \
__check_encoder(__FILE__, __LINE__, media_ ## side, media_ ## otherside, in_pt, out_pt, out_bitrate)
static void __check_encoder(const char *file, int line, struct call_media *m,
struct call_media *out_m, int in_pt, int out_pt,
int out_bitrate)
{
struct codec_handler *ch = codec_handler_lookup(m->codec_handlers, in_pt, out_m);
printf("running test %s:%i\n", file, line);
assert(ch);
assert(ch->source_pt.payload_type == in_pt);
if (ch->dest_pt.payload_type != out_pt || ch->dest_pt.bitrate != out_bitrate) {
printf("test failed: %s:%i\n", file, line);
printf("expected: %i/%i\n", out_pt, out_bitrate);
printf("received: %i/%i\n", ch->dest_pt.payload_type, ch->dest_pt.bitrate);
abort();
}
printf("test ok: %s:%i\n", file, line);
}
#endif
#define packet_seq_ts(side, pt_in, pload, rtp_ts, rtp_seq, pt_out, pload_exp, ts_exp, fatal) \
__packet_seq_ts( __FILE__, __LINE__, media_ ## side, pt_in, (str) STR_CONST_INIT(pload), \
(str) STR_CONST_INIT(pload_exp), ssrc_ ## side, rtp_ts, rtp_seq, pt_out, \
ts_exp, 1, fatal)
#define packet_seq_exp(side, pt_in, pload, rtp_ts, rtp_seq, pt_out, pload_exp, ts_diff_exp) \
__packet_seq_ts( __FILE__, __LINE__, media_ ## side, pt_in, (str) STR_CONST_INIT(pload), \
(str) STR_CONST_INIT(pload_exp), ssrc_ ## side, rtp_ts, rtp_seq, pt_out, \
-1, ts_diff_exp, 1)
static void __packet_seq_ts(const char *file, int line, struct call_media *media, long long pt_in, str pload,
str pload_exp, uint32_t ssrc, long long rtp_ts, long long rtp_seq, long long pt_out,
long long ts_exp, int seq_diff_exp, int fatal)
{
printf("running test %s:%i\n", file, line);
struct call_media *other_media;
if (media == media_A)
other_media = media_B;
else if (media == media_B)
other_media = media_A;
else
abort();
struct codec_handler *h = codec_handler_get(media, pt_in & 0x7f, other_media, NULL);
str pl = pload;
str pl_exp = pload_exp;
// from media_packet_rtp()
struct local_intf lif = { };
struct stream_fd sfd = {
.local_intf = &lif,
};
struct media_packet mp = {
.call = &call,
.media = media,
.media_out = other_media,
.ssrc_in = get_ssrc_ctx(ssrc, media->monologue->ssrc_hash, SSRC_DIR_INPUT, NULL),
.sfd = &sfd,
};
// from __stream_ssrc()
if (!media->monologue->transcoding)
mp.ssrc_in->ssrc_map_out = ntohl(ssrc);
mp.ssrc_out = get_ssrc_ctx(mp.ssrc_in->ssrc_map_out, other_media->monologue->ssrc_hash, SSRC_DIR_OUTPUT, NULL);
payload_tracker_add(&mp.ssrc_in->tracker, pt_in & 0x7f);
int packet_len = sizeof(struct rtp_header) + pl.len;
char *packet = malloc(packet_len);
struct rtp_header *rtp = (void *) packet;
*rtp = (struct rtp_header) {
.m_pt = pt_in,
.ssrc = ssrc,
.seq_num = htons(rtp_seq),
.timestamp = htonl(rtp_ts),
};
mp.rtp = rtp;
mp.payload = pl;
mp.payload.s = (packet + sizeof(struct rtp_header));
memcpy(mp.payload.s, pl.s, pl.len);
mp.raw.s = packet;
mp.raw.len = packet_len;
printf("send RTP SSRC %x seq %u TS %u PT %u\n", (unsigned int) ssrc,
(unsigned int) rtp_seq, (unsigned int) rtp_ts, (unsigned int) pt_in);
printf("send packet contents: ");
for (int i = sizeof(struct rtp_header); i < mp.raw.len; i++) {
unsigned char cc = mp.raw.s[i];
printf("\\x%02x", cc);
}
printf("\n");
h->handler_func(h, &mp);
if (pt_out == -1) {
if (mp.packets_out.length != 0) {
printf("test failed: %s:%i\n", file, line);
printf("unexpected packet\n");
abort();
}
}
else {
if (mp.packets_out.length != 1) {
printf("test failed: %s:%i\n", file, line);
printf("no packet\n");
abort();
}
struct codec_packet *cp = g_queue_pop_head(&mp.packets_out);
str cp_s = cp->s;
rtp = (void *) cp_s.s;
if (rtp->m_pt != (unsigned char) pt_out) {
printf("test failed: %s:%i\n", file, line);
printf("expected: %lli\n", pt_out);
printf("received: %i\n", rtp->m_pt);
abort();
}
printf("recv packet contents: ");
for (int i = sizeof(struct rtp_header); i < cp_s.len; i++) {
unsigned char cc = cp_s.s[i];
printf("\\x%02x", cc);
}
printf("\n");
uint32_t ts = ntohl(rtp->timestamp);
uint16_t seq = ntohs(rtp->seq_num);
uint32_t rtp_ssrc = ntohl(rtp->ssrc);
uint32_t ssrc_pt = rtp_ssrc;
printf("recv RTP SSRC %x seq %u TS %u PT %u\n", (unsigned int) rtp_ssrc,
(unsigned int) seq, (unsigned int) ts, (unsigned int) rtp->m_pt);
if (g_hash_table_contains(rtp_ts_ht, GUINT_TO_POINTER(ssrc_pt))) {
uint32_t old_ts = GPOINTER_TO_UINT(g_hash_table_lookup(rtp_ts_ht,
GUINT_TO_POINTER(ssrc_pt)));
uint32_t diff = ts - old_ts;
printf("recv RTP TS diff: %u\n", (unsigned int) diff);
if (ts_exp != -1)
assert(ts_exp == diff);
}
g_hash_table_insert(rtp_ts_ht, GUINT_TO_POINTER(ssrc_pt), GUINT_TO_POINTER(ts));
if (g_hash_table_contains(rtp_seq_ht, GUINT_TO_POINTER(ssrc_pt))) {
uint32_t old_seq = GPOINTER_TO_UINT(g_hash_table_lookup(rtp_seq_ht,
GUINT_TO_POINTER(ssrc_pt)));
uint16_t diff = seq - old_seq;
printf("recv RTP seq diff: %u (exp %u)\n", (unsigned int) diff,
(unsigned int) seq_diff_exp);
assert(diff == seq_diff_exp);
}
g_hash_table_insert(rtp_seq_ht, GUINT_TO_POINTER(ssrc_pt), GUINT_TO_POINTER(seq));
if (str_shift(&cp_s, sizeof(struct rtp_header)))
abort();
if (pl_exp.len != cp_s.len)
abort();
if (fatal && memcmp(pl_exp.s, cp_s.s, pl_exp.len))
abort();
codec_packet_free(cp);
}
printf("test ok: %s:%i\n\n", file, line);
free(packet);
ssrc_ctx_put(&mp.ssrc_in);
ssrc_ctx_put(&mp.ssrc_out);
}
#define packet(side, pt_in, pload, pt_out, pload_exp) \
packet_seq(side, pt_in, pload, 0, 0, pt_out, pload_exp)
#define packet_seq(side, pt_in, pload, rtp_ts, rtp_seq, pt_out, pload_exp) \
packet_seq_ts(side, pt_in, pload, rtp_ts, rtp_seq, pt_out, pload_exp, -1, 1)
#define packet_seq_nf(side, pt_in, pload, rtp_ts, rtp_seq, pt_out, pload_exp) \
packet_seq_ts(side, pt_in, pload, rtp_ts, rtp_seq, pt_out, pload_exp, -1, 0)
static void end(void) {
g_hash_table_destroy(rtp_ts_ht);
g_hash_table_destroy(rtp_seq_ht);
g_queue_clear_full(&media_A->streams, free);
g_queue_clear_full(&media_B->streams, free);
call_media_free(&media_A);
call_media_free(&media_B);
bencode_buffer_free(&call.buffer);
g_hash_table_destroy(call.tags);
g_queue_clear(&call.medias);
if (ml_A)
__monologue_free(ml_A);
if (ml_B)
__monologue_free(ml_B);
__cleanup();
printf("\n");
}
static void dtmf(const char *s) {
if (!dtmf_logs) {
if (strlen(s) != 0)
abort();
return;
}
if (strlen(s) != dtmf_logs->len) {
printf("DTMF mismatch: \"%s\" != \"%s\"\n", s, dtmf_logs->str);
abort();
}
if (memcmp(s, dtmf_logs->str, dtmf_logs->len) != 0) {
printf("DTMF mismatch: \"%s\" != \"%s\"\n", s, dtmf_logs->str);
abort();
}
printf("DTMF log ok; contents: \"%s\"\n", dtmf_logs->str);
g_string_assign(dtmf_logs, "");
}
#define PCMU_payload "\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00"
#define PCMA_payload "\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a\x2b\x2a"
#define PCMA_silence "\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5"
#define PCMU_silence "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
#define G722_payload "\x23\x84\x20\x84\x20\x84\x04\x84\x04\x04\x84\x04\x84\x04\x84\x05\x85\x46\x87\x48\xc8\x48\x88\x48\xc8\x49\x8a\x4b\xcc\x4c\x8c\x4c\xcc\x4c\x8c\x4d\xce\x50\xcf\x51\x90\x50\xcf\x12\xd1\x52\xd2\x54\x91\x52\xd2\x54\x92\x54\xd3\x56\x93\xd6\x94\xd4\x93\xd7\xd5\x55\x94\x55\xd5\x55\xd4\x56\xd5\x17\xd7\x5a\x95\xd7\x97\xd9\xd4\x16\x58\x57\x98\xd5\xd7\x5b\x96\xda\xd6\x1b\x57\x5a\xd6\x1a\x57\x5b\x98\xd6\xd8\x56\x98\xd7\xd9\x5a\x95\xdb\xd6\x1c\x52\x5e\xd7\x5c\x93\xdf\x99\xd5\xd7\x5f\xd9\x14\x56\x7f\x92\xda\xd9\x5c\x92\xdd\xd7\x5d\x92\xff\xd6\x5a\x96\xdc\xd5\x18\x56\x7e\xd2\x5e\x96\xde\x94\xd8\xd8\x58\xd3\x79\x93\xfb\x90\xdc\xd6\x5b\xdd\x58\x96\xff"
#define AMR_WB_payload "\xf0\x1c\xf3\x06\x08\x10\x77\x32\x23\x20\xd3\x50\x62\x12\xc7\x7c\xe2\xea\x84\x0e\x6e\xf4\x4d\xe4\x7f\xc9\x4c\xcc\x58\x5d\xed\xcc\x5d\x7c\x6c\x14\x7d\xc0" // octet aligned
#define AMR_WB_payload_noe "\xf1\xfc\xc1\x82\x04\x1d\xcc\x88\xc8\x34\xd4\x18\x84\xb1\xdf\x38\xba\xa1\x03\x9b\xbd\x13\x79\x1f\xf2\x53\x33\x16\x17\x7b\x73\x17\x5f\x1b\x05\x1f\x70" // bandwidth efficient
int main(void) {
rtpe_common_config_ptr = &rtpe_config.common;
unsigned long random_seed = 0;
codeclib_init(0);
RAND_seed(&random_seed, sizeof(random_seed));
statistics_init();
codecs_init();
// plain
start();
sdp_pt(0, PCMU, 8000);
offer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000");
sdp_pt(0, PCMU, 8000);
answer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000");
packet(A, 0, PCMU_payload, 0, PCMU_payload);
packet(B, 0, PCMU_payload, 0, PCMU_payload);
end();
// plain with two offered and two answered
start();
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
offer();
expect(A, "0/PCMU/8000 8/PCMA/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000");
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
answer();
expect(A, "0/PCMU/8000 8/PCMA/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000");
packet_seq(A, 0, PCMU_payload, 0, 0, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 0, 0, 0, PCMU_payload);
packet_seq(A, 8, PCMA_payload, 160, 1, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 160, 1, 8, PCMA_payload);
end();
// plain with two offered and one answered
start();
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
offer();
expect(A, "0/PCMU/8000 8/PCMA/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000");
sdp_pt(8, PCMA, 8000);
answer();
expect(A, "8/PCMA/8000");
expect(B, "8/PCMA/8000");
packet(A, 8, PCMA_payload, 8, PCMA_payload);
packet(B, 8, PCMA_payload, 8, PCMA_payload);
end();
// plain with two offered and two answered + always-transcode one way
start();
c_accept(all);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
offer();
expect(A, "0/PCMU/8000 8/PCMA/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000");
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
answer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000");
packet_seq(A, 0, PCMU_payload, 0, 0, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 0, 0, 0, PCMU_payload);
packet_seq(B, 8, PCMA_payload, 160, 1, 0, PCMU_payload);
end();
// plain with two offered and two answered + always-transcode both ways
start();
c_accept(all);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
offer();
expect(A, "0/PCMU/8000 8/PCMA/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000");
c_accept(all);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
answer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000");
packet_seq(A, 0, PCMU_payload, 0, 0, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 0, 0, 0, PCMU_payload);
packet_seq(B, 8, PCMA_payload, 160, 1, 0, PCMU_payload);
end();
// add one codec to transcode
start();
sdp_pt(0, PCMU, 8000);
transcode(PCMA);
offer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000");
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
answer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000");
packet(A, 0, PCMU_payload, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 0, 0, 0, PCMU_payload);
packet_seq(B, 8, PCMA_payload, 160, 1, 0, PCMU_payload);
end();
// add one codec to transcode, don't accept original offered codec
start();
sdp_pt(0, PCMU, 8000);
transcode(PCMA);
offer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000");
sdp_pt(8, PCMA, 8000);
answer();
expect(A, "0/PCMU/8000");
expect(B, "8/PCMA/8000");
packet(A, 0, PCMU_payload, 8, PCMA_payload);
packet(B, 8, PCMA_payload, 0, PCMU_payload);
end();
#ifdef WITH_AMR_TESTS
{
str codec_name = STR_CONST_INIT("AMR-WB");
codec_def_t *def = codec_find(&codec_name, MT_AUDIO);
assert(def);
if (def->support_encoding && def->support_decoding) {
// forward AMR-WB
start();
sdp_pt(0, PCMU, 8000);
transcode(AMR-WB);
offer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000 96/AMR-WB/16000/octet-align=1;mode-change-capability=2");
sdp_pt_fmt(96, AMR-WB, 16000, "octet-align=1");
answer();
expect(A, "0/PCMU/8000");
expect(B, "96/AMR-WB/16000/octet-align=1");
packet_seq(A, 0, PCMU_payload, 0, 0, -1, ""); // nothing due to resampling buffer
packet_seq_nf(A, 0, PCMU_payload, 160, 1, 96, AMR_WB_payload);
packet_seq(B, 96, AMR_WB_payload, 0, 0, -1, ""); // nothing due to resampling/decoding buffer
packet_seq_nf(B, 96, AMR_WB_payload, 320, 1, 0, PCMU_payload);
end();
// reverse AMR-WB (octet aligned)
start();
sdp_pt_fmt(96, AMR-WB, 16000, "octet-align=1");
transcode(PCMU);
offer();
expect(A, "96/AMR-WB/16000/octet-align=1");
expect(B, "96/AMR-WB/16000/octet-align=1 0/PCMU/8000");
sdp_pt(0, PCMU, 8000);
answer();
expect(A, "96/AMR-WB/16000/octet-align=1");
expect(B, "0/PCMU/8000");
packet_seq(B, 0, PCMU_payload, 0, 0, -1, ""); // nothing due to resampling buffer
packet_seq_nf(B, 0, PCMU_payload, 160, 1, 96, AMR_WB_payload);
packet_seq(A, 96, AMR_WB_payload, 0, 0, -1, ""); // nothing due to resampling/decoding buffer
packet_seq_nf(A, 96, AMR_WB_payload, 320, 1, 0, PCMU_payload);
end();
// reverse AMR-WB (bandwidth efficient)
start();
sdp_pt(96, AMR-WB, 16000);
transcode(PCMU);
offer();
expect(A, "96/AMR-WB/16000");
expect(B, "96/AMR-WB/16000 0/PCMU/8000");
sdp_pt(0, PCMU, 8000);
answer();
expect(A, "96/AMR-WB/16000");
expect(B, "0/PCMU/8000");
packet_seq(B, 0, PCMU_payload, 0, 0, -1, ""); // nothing due to resampling buffer
packet_seq_nf(B, 0, PCMU_payload, 160, 1, 96, AMR_WB_payload_noe);
packet_seq(A, 96, AMR_WB_payload_noe, 0, 0, -1, ""); // nothing due to resampling/decoding buffer
packet_seq_nf(A, 96, AMR_WB_payload_noe, 320, 1, 0, PCMU_payload);
end();
}
}
{
str codec_name = STR_CONST_INIT("AMR");
codec_def_t *def = codec_find(&codec_name, MT_AUDIO);
assert(def);
if (def->support_encoding && def->support_decoding) {
// default bitrate
start();
sdp_pt(0, PCMU, 8000);
transcode(AMR);
offer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000 96/AMR/8000/octet-align=1;mode-change-capability=2");
sdp_pt_fmt(96, AMR, 8000, "octet-align=1");
answer();
expect(A, "0/PCMU/8000");
expect(B, "96/AMR/8000/octet-align=1");
check_encoder(A, B, 0, 96, 0); // uses codec default
check_encoder(B, A, 96, 0, 0);
end();
// default bitrate reverse
start();
sdp_pt(96, AMR, 8000);
transcode(PCMU);
offer();
expect(A, "96/AMR/8000");
expect(B, "96/AMR/8000 0/PCMU/8000");
sdp_pt(0, PCMU, 8000);
answer();
expect(A, "96/AMR/8000");
expect(B, "0/PCMU/8000");
check_encoder(A, B, 96, 0, 0);
check_encoder(B, A, 0, 96, 0); // uses codec default
end();
// specify forward bitrate
start();
sdp_pt(0, PCMU, 8000);
transcode(AMR/8000/1/6700);
offer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000 96/AMR/8000/octet-align=1;mode-change-capability=2");
sdp_pt_fmt(96, AMR, 8000, "octet-align=1");
answer();
expect(A, "0/PCMU/8000");
expect(B, "96/AMR/8000/octet-align=1");
check_encoder(A, B, 0, 96, 6700);
check_encoder(B, A, 96, 0, 0);
end();
// specify non-default forward bitrate
start();
sdp_pt(0, PCMU, 8000);
transcode(AMR/8000/1/7400);
offer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000 96/AMR/8000/octet-align=1;mode-change-capability=2");
sdp_pt_fmt(96, AMR, 8000, "octet-align=1");
answer();
expect(A, "0/PCMU/8000");
expect(B, "96/AMR/8000/octet-align=1");
check_encoder(A, B, 0, 96, 7400);
check_encoder(B, A, 96, 0, 0);
end();
// specify reverse bitrate
start();
sdp_pt(96, AMR, 8000);
transcode(PCMU);
codec_set("AMR/8000/1/6700");
offer();
expect(A, "96/AMR/8000");
expect(B, "96/AMR/8000 0/PCMU/8000");
sdp_pt(0, PCMU, 8000);
answer();
expect(A, "96/AMR/8000");
expect(B, "0/PCMU/8000");
check_encoder(A, B, 96, 0, 0);
check_encoder(B, A, 0, 96, 6700);
end();
// specify non-default reverse bitrate
start();
sdp_pt(96, AMR, 8000);
transcode(PCMU);
codec_set("AMR/8000/1/7400");
offer();
expect(A, "96/AMR/8000");
expect(B, "96/AMR/8000 0/PCMU/8000");
sdp_pt(0, PCMU, 8000);
answer();
expect(A, "96/AMR/8000");
expect(B, "0/PCMU/8000");
check_encoder(A, B, 96, 0, 0);
check_encoder(B, A, 0, 96, 7400);
end();
}
}
#endif
// G.722 <> PCMA
start();
sdp_pt(8, PCMA, 8000);
transcode(G722);
offer();
expect(A, "8/PCMA/8000");
expect(B, "8/PCMA/8000 9/G722/8000");
sdp_pt(9, G722, 8000);
answer();
expect(A, "8/PCMA/8000");
expect(B, "9/G722/8000");
packet_seq(A, 8, PCMA_payload, 0, 0, -1, ""); // nothing due to resampling
packet_seq_nf(A, 8, PCMA_payload, 160, 1, 9, G722_payload);
packet_seq_ts(A, 8, PCMA_payload, 320, 2, 9, G722_payload, 160, 0);
packet_seq(B, 9, G722_payload, 0, 0, -1, ""); // nothing due to resampling
packet_seq_nf(B, 9, G722_payload, 160, 1, 8, PCMA_payload);
packet_seq_ts(B, 9, G722_payload, 320, 2, 8, PCMA_payload, 160, 0);
end();
// A includes unsupported codec by B - no transcoding (GH#562 control case)
start();
sdp_pt(97, opus, 48000);
sdp_pt(9, G722, 8000);
sdp_pt(8, PCMA, 8000);
offer();
expect(A, "97/opus/48000 9/G722/8000 8/PCMA/8000");
expect(B, "97/opus/48000 9/G722/8000 8/PCMA/8000");
sdp_pt(9, G722, 8000);
sdp_pt(8, PCMA, 8000);
answer();
expect(A, "9/G722/8000 8/PCMA/8000");
expect(B, "9/G722/8000 8/PCMA/8000");
end();
// A includes unsupported codec by B - transcoded codec accepted (GH#562 control case)
start();
sdp_pt(97, opus, 48000);
sdp_pt(9, G722, 8000);
sdp_pt(8, PCMA, 8000);
transcode(PCMU); // standin for G729
offer();
expect(A, "97/opus/48000 9/G722/8000 8/PCMA/8000");
expect(B, "97/opus/48000 9/G722/8000 8/PCMA/8000 0/PCMU/8000");
sdp_pt(9, G722, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
answer();
expect(A, "9/G722/8000 8/PCMA/8000 97/opus/48000");
expect(B, "9/G722/8000 8/PCMA/8000 0/PCMU/8000");
end();
// A includes unsupported codec by B - transcoded codec rejected (GH#562)
start();
sdp_pt(97, opus, 48000);
sdp_pt(9, G722, 8000);
sdp_pt(8, PCMA, 8000);
transcode(PCMU); // standin for G729
offer();
expect(A, "97/opus/48000 9/G722/8000 8/PCMA/8000");
expect(B, "97/opus/48000 9/G722/8000 8/PCMA/8000 0/PCMU/8000");
sdp_pt(9, G722, 8000);
sdp_pt(8, PCMA, 8000);
answer();
expect(A, "9/G722/8000 8/PCMA/8000");
expect(B, "9/G722/8000 8/PCMA/8000");
end();
_log_facility_dtmf = 1; // dummy enabler
// plain DTMF passthrough w/o transcoding
start();
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
offer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
packet_seq(A, 8, PCMA_payload, 1000000, 200, 8, PCMA_payload);
// start with marker
packet_seq(A, 101 | 0x80, "\x08\x0a\x00\xa0", 1000160, 201, 101 | 0x80, "\x08\x0a\x00\xa0");
dtmf("");
// continuous event with increasing length
// XXX check output ts, seq, ssrc
packet_seq(A, 101, "\x08\x0a\x01\x40", 1000160, 202, 101, "\x08\x0a\x01\x40");
packet_seq(A, 101, "\x08\x0a\x01\xe0", 1000160, 203, 101, "\x08\x0a\x01\xe0");
packet_seq(A, 101, "\x08\x0a\x02\x80", 1000160, 204, 101, "\x08\x0a\x02\x80");
dtmf("");
// end
packet_seq(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"\",\"event\":8,\"duration\":100,\"volume\":10}");
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
dtmf("");
// send some more audio
packet_seq(A, 8, PCMA_payload, 1000960, 206, 8, PCMA_payload);
packet_seq(A, 8, PCMA_payload, 1001120, 207, 8, PCMA_payload);
// start with marker
packet_seq(A, 101 | 0x80, "\x05\x0a\x00\xa0", 1001280, 208, 101 | 0x80, "\x05\x0a\x00\xa0");
dtmf("");
// continuous event with increasing length
packet_seq(A, 101, "\x05\x0a\x01\x40", 1001280, 209, 101, "\x05\x0a\x01\x40");
packet_seq(A, 101, "\x05\x0a\x01\xe0", 1001280, 210, 101, "\x05\x0a\x01\xe0");
dtmf("");
// end
packet_seq(A, 101, "\x05\x8a\x02\x80", 1001280, 211, 101, "\x05\x8a\x02\x80");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"\",\"event\":5,\"duration\":80,\"volume\":10}");
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, 101, "\x05\x8a\x02\x80", 0);
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, 101, "\x05\x8a\x02\x80", 0);
dtmf("");
// final audio RTP test
packet_seq(A, 8, PCMA_payload, 1000960, 212, 8, PCMA_payload);
end();
// DTMF passthrough w/ transcoding
start();
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
transcode(PCMU);
offer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 0/PCMU/8000 101/telephone-event/8000");
sdp_pt(0, PCMU, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "0/PCMU/8000 101/telephone-event/8000");
packet_seq(A, 8, PCMA_payload, 1000000, 200, 0, PCMU_payload);
// start with marker
packet_seq(A, 101 | 0x80, "\x08\x0a\x00\xa0", 1000160, 201, 101 | 0x80, "\x08\x0a\x00\xa0");
dtmf("");
// continuous event with increasing length
// XXX check output ts, seq, ssrc
packet_seq(A, 101, "\x08\x0a\x01\x40", 1000160, 202, 101, "\x08\x0a\x01\x40");
packet_seq(A, 101, "\x08\x0a\x01\xe0", 1000160, 203, 101, "\x08\x0a\x01\xe0");
packet_seq(A, 101, "\x08\x0a\x02\x80", 1000160, 204, 101, "\x08\x0a\x02\x80");
dtmf("");
// end
packet_seq(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"\",\"event\":8,\"duration\":100,\"volume\":10}");
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
dtmf("");
// send some more audio
packet_seq(A, 8, PCMA_payload, 1000960, 206, 0, PCMU_payload);
packet_seq(A, 8, PCMA_payload, 1001120, 207, 0, PCMU_payload);
// start with marker
packet_seq(A, 101 | 0x80, "\x05\x0a\x00\xa0", 1001280, 208, 101 | 0x80, "\x05\x0a\x00\xa0");
dtmf("");
// continuous event with increasing length
packet_seq(A, 101, "\x05\x0a\x01\x40", 1001280, 209, 101, "\x05\x0a\x01\x40");
packet_seq(A, 101, "\x05\x0a\x01\xe0", 1001280, 210, 101, "\x05\x0a\x01\xe0");
dtmf("");
// end
packet_seq(A, 101, "\x05\x8a\x02\x80", 1001280, 211, 101, "\x05\x8a\x02\x80");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"\",\"event\":5,\"duration\":80,\"volume\":10}");
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, 101, "\x05\x8a\x02\x80", 0);
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, 101, "\x05\x8a\x02\x80", 0);
dtmf("");
// final audio RTP test
packet_seq(A, 8, PCMA_payload, 1000960, 212, 0, PCMU_payload);
end();
// plain DTMF passthrough w/o transcoding w/ implicit primary payload type
start();
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
offer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
packet_seq(A, 0, PCMU_payload, 1000000, 200, 0, PCMU_payload);
// start with marker
packet_seq(A, 101 | 0x80, "\x08\x0a\x00\xa0", 1000160, 201, 101 | 0x80, "\x08\x0a\x00\xa0");
dtmf("");
// continuous event with increasing length
// XXX check output ts, seq, ssrc
packet_seq(A, 101, "\x08\x0a\x01\x40", 1000160, 202, 101, "\x08\x0a\x01\x40");
packet_seq(A, 101, "\x08\x0a\x01\xe0", 1000160, 203, 101, "\x08\x0a\x01\xe0");
packet_seq(A, 101, "\x08\x0a\x02\x80", 1000160, 204, 101, "\x08\x0a\x02\x80");
dtmf("");
// end
packet_seq(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"\",\"event\":8,\"duration\":100,\"volume\":10}");
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
dtmf("");
// send some more audio
packet_seq(A, 0, PCMU_payload, 1000960, 206, 0, PCMU_payload);
packet_seq(A, 0, PCMU_payload, 1001120, 207, 0, PCMU_payload);
// start with marker
packet_seq(A, 101 | 0x80, "\x05\x0a\x00\xa0", 1001280, 208, 101 | 0x80, "\x05\x0a\x00\xa0");
dtmf("");
// continuous event with increasing length
packet_seq(A, 101, "\x05\x0a\x01\x40", 1001280, 209, 101, "\x05\x0a\x01\x40");
packet_seq(A, 101, "\x05\x0a\x01\xe0", 1001280, 210, 101, "\x05\x0a\x01\xe0");
dtmf("");
// end
packet_seq(A, 101, "\x05\x8a\x02\x80", 1001280, 211, 101, "\x05\x8a\x02\x80");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"\",\"event\":5,\"duration\":80,\"volume\":10}");
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, 101, "\x05\x8a\x02\x80", 0);
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, 101, "\x05\x8a\x02\x80", 0);
dtmf("");
// final audio RTP test
packet_seq(A, 0, PCMU_payload, 1000960, 212, 0, PCMU_payload);
end();
// plain DTMF passthrough w/o transcoding - blocking
start();
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
offer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
packet_seq(A, 8, PCMA_payload, 1000000, 200, 8, PCMA_payload);
// start with marker
packet_seq(A, 101 | 0x80, "\x08\x0a\x00\xa0", 1000160, 201, 101 | 0x80, "\x08\x0a\x00\xa0");
dtmf("");
// continuous event with increasing length
// XXX check output ts, seq, ssrc
packet_seq(A, 101, "\x08\x0a\x01\x40", 1000160, 202, 101, "\x08\x0a\x01\x40");
packet_seq(A, 101, "\x08\x0a\x01\xe0", 1000160, 203, 101, "\x08\x0a\x01\xe0");
packet_seq(A, 101, "\x08\x0a\x02\x80", 1000160, 204, 101, "\x08\x0a\x02\x80");
dtmf("");
// end
packet_seq(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"\",\"event\":8,\"duration\":100,\"volume\":10}");
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
dtmf("");
// send some more audio
packet_seq(A, 8, PCMA_payload, 1000960, 206, 8, PCMA_payload);
packet_seq(A, 8, PCMA_payload, 1001120, 207, 8, PCMA_payload);
// enable blocking
call.block_dtmf = BLOCK_DTMF_DROP;
// start with marker
packet_seq_exp(A, 101 | 0x80, "\x05\x0a\x00\xa0", 1001280, 208, -1, "", 0);
dtmf("");
// continuous event with increasing length
packet_seq(A, 101, "\x05\x0a\x01\x40", 1001280, 209, -1, "");
packet_seq(A, 101, "\x05\x0a\x01\xe0", 1001280, 210, -1, "");
dtmf("");
// end
packet_seq(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"\",\"event\":5,\"duration\":80,\"volume\":10}");
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "", 0);
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "", 0);
dtmf("");
// final audio RTP test
packet_seq_exp(A, 8, PCMA_payload, 1000960, 212, 8, PCMA_payload, 5); // DTMF packets appear lost
packet_seq(A, 8, PCMA_payload, 1001120, 213, 8, PCMA_payload);
// media blocking
ml_A->block_media = 1;
packet_seq_exp(A, 8, PCMA_payload, 1001280, 214, -1, "", 0);
packet_seq_exp(A, 8, PCMA_payload, 1001440, 215, -1, "", 0);
ml_A->block_media = 0;
packet_seq_exp(A, 8, PCMA_payload, 1001600, 216, 8, PCMA_payload, 3); // media packets appear lost
call.block_media = 1;
packet_seq_exp(A, 8, PCMA_payload, 1001760, 217, -1, "", 0);
packet_seq_exp(A, 8, PCMA_payload, 1001920, 218, -1, "", 0);
call.block_media = 0;
packet_seq_exp(A, 8, PCMA_payload, 1002080, 219, 8, PCMA_payload, 3); // media packets appear lost
ml_B->block_media = 1;
packet_seq(A, 8, PCMA_payload, 1002240, 220, 8, PCMA_payload);
end();
// DTMF passthrough w/ transcoding - blocking
start();
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
transcode(PCMU);
offer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 0/PCMU/8000 101/telephone-event/8000");
sdp_pt(0, PCMU, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "0/PCMU/8000 101/telephone-event/8000");
packet_seq(A, 8, PCMA_payload, 1000000, 200, 0, PCMU_payload);
// start with marker
packet_seq(A, 101 | 0x80, "\x08\x0a\x00\xa0", 1000160, 201, 101 | 0x80, "\x08\x0a\x00\xa0");
dtmf("");
// continuous event with increasing length
// XXX check output ts, seq, ssrc
packet_seq(A, 101, "\x08\x0a\x01\x40", 1000160, 202, 101, "\x08\x0a\x01\x40");
packet_seq(A, 101, "\x08\x0a\x01\xe0", 1000160, 203, 101, "\x08\x0a\x01\xe0");
packet_seq(A, 101, "\x08\x0a\x02\x80", 1000160, 204, 101, "\x08\x0a\x02\x80");
dtmf("");
// end
packet_seq(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"\",\"event\":8,\"duration\":100,\"volume\":10}");
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
dtmf("");
// send some more audio
packet_seq(A, 8, PCMA_payload, 1000960, 206, 0, PCMU_payload);
packet_seq(A, 8, PCMA_payload, 1001120, 207, 0, PCMU_payload);
// enable blocking
call.block_dtmf = BLOCK_DTMF_DROP;
// start with marker
packet_seq_exp(A, 101 | 0x80, "\x05\x0a\x00\xa0", 1001280, 208, -1, "", 0);
dtmf("");
// continuous event with increasing length
packet_seq(A, 101, "\x05\x0a\x01\x40", 1001280, 209, -1, "");
packet_seq(A, 101, "\x05\x0a\x01\xe0", 1001280, 210, -1, "");
dtmf("");
// end
packet_seq(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"\",\"event\":5,\"duration\":80,\"volume\":10}");
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "", 0);
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "", 0);
dtmf("");
// final audio RTP test
packet_seq_exp(A, 8, PCMA_payload, 1000960, 212, 0, PCMU_payload, 5); // DTMF packets appear lost
packet_seq(A, 8, PCMA_payload, 1001120, 213, 0, PCMU_payload);
// media blocking
ml_A->block_media = 1;
packet_seq_exp(A, 8, PCMA_payload, 1001280, 214, -1, "", 0);
packet_seq_exp(A, 8, PCMA_payload, 1001440, 215, -1, "", 0);
ml_A->block_media = 0;
packet_seq_exp(A, 8, PCMA_payload, 1001600, 214, 0, PCMU_payload, 1); // cheat with the seq here - 216 would get held by the jitter buffer
call.block_media = 1;
packet_seq_exp(A, 8, PCMA_payload, 1001760, 215, -1, "", 0);
packet_seq_exp(A, 8, PCMA_payload, 1001920, 216, -1, "", 0);
call.block_media = 0;
packet_seq_exp(A, 8, PCMA_payload, 1002080, 215, 0, PCMU_payload, 1);
ml_B->block_media = 1;
packet_seq_exp(A, 8, PCMA_payload, 1002240, 216, 0, PCMU_payload, 1);
end();
// plain DTMF passthrough w/o transcoding w/ implicit primary payload type - blocking
start();
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
offer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
packet_seq(A, 0, PCMU_payload, 1000000, 200, 0, PCMU_payload);
// start with marker
packet_seq(A, 101 | 0x80, "\x08\x0a\x00\xa0", 1000160, 201, 101 | 0x80, "\x08\x0a\x00\xa0");
dtmf("");
// continuous event with increasing length
// XXX check output ts, seq, ssrc
packet_seq(A, 101, "\x08\x0a\x01\x40", 1000160, 202, 101, "\x08\x0a\x01\x40");
packet_seq(A, 101, "\x08\x0a\x01\xe0", 1000160, 203, 101, "\x08\x0a\x01\xe0");
packet_seq(A, 101, "\x08\x0a\x02\x80", 1000160, 204, 101, "\x08\x0a\x02\x80");
dtmf("");
// end
packet_seq(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"\",\"event\":8,\"duration\":100,\"volume\":10}");
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
packet_seq_exp(A, 101, "\x08\x8a\x03\x20", 1000160, 205, 101, "\x08\x8a\x03\x20", 0);
dtmf("");
// send some more audio
packet_seq(A, 0, PCMU_payload, 1000960, 206, 0, PCMU_payload);
packet_seq(A, 0, PCMU_payload, 1001120, 207, 0, PCMU_payload);
// enable blocking
call.block_dtmf = BLOCK_DTMF_DROP;
// start with marker
packet_seq_exp(A, 101 | 0x80, "\x05\x0a\x00\xa0", 1001280, 208, -1, "", 0);
dtmf("");
// continuous event with increasing length
packet_seq(A, 101, "\x05\x0a\x01\x40", 1001280, 209, -1, "");
packet_seq(A, 101, "\x05\x0a\x01\xe0", 1001280, 210, -1, "");
dtmf("");
// end
packet_seq(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "");
dtmf("{\"callid\":\"test-call\",\"source_tag\":\"tag_A\",\"tags\":[],\"type\":\"DTMF\",\"timestamp\":0,\"source_ip\":\"\",\"event\":5,\"duration\":80,\"volume\":10}");
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "", 0);
packet_seq_exp(A, 101, "\x05\x8a\x02\x80", 1001280, 211, -1, "", 0);
dtmf("");
// final audio RTP test
packet_seq_exp(A, 0, PCMU_payload, 1000960, 212, 0, PCMU_payload, 5); // DTMF packets appear lost
packet_seq(A, 0, PCMU_payload, 1001120, 213, 0, PCMU_payload);
// media blocking
ml_A->block_media = 1;
packet_seq_exp(A, 0, PCMU_payload, 1001280, 214, -1, "", 0);
packet_seq_exp(A, 0, PCMU_payload, 1001440, 215, -1, "", 0);
ml_A->block_media = 0;
packet_seq_exp(A, 0, PCMU_payload, 1001600, 216, 0, PCMU_payload, 3); // media packets appear lost
call.block_media = 1;
packet_seq_exp(A, 0, PCMU_payload, 1001760, 217, -1, "", 0);
packet_seq_exp(A, 0, PCMU_payload, 1001920, 218, -1, "", 0);
call.block_media = 0;
packet_seq_exp(A, 0, PCMU_payload, 1002080, 219, 0, PCMU_payload, 3); // media packets appear lost
ml_B->block_media = 1;
packet_seq(A, 0, PCMU_payload, 1002240, 220, 0, PCMU_payload);
end();
// codec-mask/accept/consume tests
// control - plain in/out
start();
sdp_pt(104, SILK, 16000);
sdp_pt(9, G722, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
sdp_pt(13, CN, 8000);
sdp_pt(118, CN, 16000);
offer();
expect(A, "104/SILK/16000 9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000 118/CN/16000");
expect(B, "104/SILK/16000 9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000 118/CN/16000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
end();
// codec-mask only
start();
sdp_pt(104, SILK, 16000);
sdp_pt(9, G722, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
sdp_pt(13, CN, 8000);
sdp_pt(118, CN, 16000);
c_mask(PCMU);
offer();
expect(A, "104/SILK/16000 9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000 118/CN/16000");
expect(B, "104/SILK/16000 9/G722/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000 118/CN/16000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
end();
// codec-mask + transcode + reject transcoded codec
start();
sdp_pt(104, SILK, 16000);
sdp_pt(9, G722, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
sdp_pt(13, CN, 8000);
sdp_pt(118, CN, 16000);
c_mask(PCMU);
transcode(GSM);
offer();
expect(A, "104/SILK/16000 9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000 118/CN/16000");
expect(B, "9/G722/8000 8/PCMA/8000 3/GSM/8000 101/telephone-event/8000 13/CN/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "8/PCMA/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
end();
// codec-mask + transcode + accept transcoded codec
start();
sdp_pt(104, SILK, 16000);
sdp_pt(9, G722, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
sdp_pt(13, CN, 8000);
sdp_pt(118, CN, 16000);
c_mask(PCMU);
transcode(GSM);
offer();
expect(A, "104/SILK/16000 9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000 118/CN/16000");
expect(B, "9/G722/8000 8/PCMA/8000 3/GSM/8000 101/telephone-event/8000 13/CN/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(3, GSM, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "8/PCMA/8000 9/G722/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 3/GSM/8000 101/telephone-event/8000");
// G.722 > PCMA
packet_seq(A, 9, G722_payload, 0, 0, -1, ""); // nothing due to resampling
packet_seq_nf(A, 9, G722_payload, 160, 1, 8, PCMA_payload);
packet_seq_ts(A, 9, G722_payload, 320, 2, 8, PCMA_payload, 160, 0);
// asymmetric codec
packet(B, 8, PCMA_payload, 8, PCMA_payload); // nothing due to resampling
end();
// codec-consume only
start();
sdp_pt(104, SILK, 16000);
sdp_pt(9, G722, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
sdp_pt(13, CN, 8000);
sdp_pt(118, CN, 16000);
c_consume(PCMU);
offer();
expect(A, "104/SILK/16000 9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000 118/CN/16000");
expect(B, "9/G722/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "0/PCMU/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
end();
// codec-consume + transcode + reject transcoded codec
start();
sdp_pt(104, SILK, 16000);
sdp_pt(9, G722, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
sdp_pt(13, CN, 8000);
sdp_pt(118, CN, 16000);
c_consume(PCMU);
transcode(GSM);
offer();
expect(A, "104/SILK/16000 9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000 118/CN/16000");
expect(B, "9/G722/8000 8/PCMA/8000 3/GSM/8000 101/telephone-event/8000 13/CN/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "0/PCMU/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
end();
// codec-consume + transcode + accept transcoded codec
start();
sdp_pt(104, SILK, 16000);
sdp_pt(9, G722, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
sdp_pt(13, CN, 8000);
sdp_pt(118, CN, 16000);
c_consume(PCMU);
transcode(GSM);
offer();
expect(A, "104/SILK/16000 9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000 118/CN/16000");
expect(B, "9/G722/8000 8/PCMA/8000 3/GSM/8000 101/telephone-event/8000 13/CN/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(3, GSM, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "0/PCMU/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 3/GSM/8000 101/telephone-event/8000");
end();
// codec-accept only
start();
sdp_pt(104, SILK, 16000);
sdp_pt(9, G722, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
sdp_pt(13, CN, 8000);
sdp_pt(118, CN, 16000);
c_accept(PCMU);
offer();
expect(A, "104/SILK/16000 9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000 118/CN/16000");
expect(B, "9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "0/PCMU/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
end();
// codec-accept + transcode + reject transcoded codec
start();
sdp_pt(104, SILK, 16000);
sdp_pt(9, G722, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
sdp_pt(13, CN, 8000);
sdp_pt(118, CN, 16000);
c_accept(PCMU);
transcode(GSM);
offer();
expect(A, "104/SILK/16000 9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000 118/CN/16000");
expect(B, "9/G722/8000 0/PCMU/8000 8/PCMA/8000 3/GSM/8000 101/telephone-event/8000 13/CN/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "0/PCMU/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
end();
// codec-accept + transcode + accept transcoded codec
start();
sdp_pt(104, SILK, 16000);
sdp_pt(9, G722, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
sdp_pt(13, CN, 8000);
sdp_pt(118, CN, 16000);
c_accept(PCMU);
transcode(GSM);
offer();
expect(A, "104/SILK/16000 9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000 118/CN/16000");
expect(B, "9/G722/8000 0/PCMU/8000 8/PCMA/8000 3/GSM/8000 101/telephone-event/8000 13/CN/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(3, GSM, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "0/PCMU/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 3/GSM/8000 101/telephone-event/8000");
end();
// codec-accept first codec
start();
sdp_pt(104, SILK, 16000);
sdp_pt(9, G722, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
sdp_pt(13, CN, 8000);
sdp_pt(118, CN, 16000);
c_accept(G722);
offer();
expect(A, "104/SILK/16000 9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000 118/CN/16000");
expect(B, "9/G722/8000 0/PCMU/8000 8/PCMA/8000 101/telephone-event/8000 13/CN/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "9/G722/8000 101/telephone-event/8000");
expect(B, "8/PCMA/8000 101/telephone-event/8000");
end();
// gh 664 codec masking a/t
start();
sdp_pt(120, opus, 48000);
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(101, telephone-event, 8000);
c_mask(opus);
c_mask(G722);
c_mask(G7221);
c_accept(all);
offer();
expect(B, "8/PCMA/8000 0/PCMU/8000 101/telephone-event/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "120/opus/48000");
end();
// gh 664 codec masking accept=all
start();
sdp_pt(120, opus, 48000);
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(101, telephone-event, 8000);
c_mask(opus);
c_mask(G722);
c_mask(G7221);
c_accept(all);
offer();
expect(B, "8/PCMA/8000 0/PCMU/8000 101/telephone-event/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
answer();
expect(A, "120/opus/48000");
end();
// CN transcoding
rtpe_config.silence_detect_int = 10 << 16;
str_init_len(&rtpe_config.cn_payload, "\x40", 1);
// CN transcoding - forward
start();
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
transcode(CN);
offer();
expect(B, "8/PCMA/8000 0/PCMU/8000 13/CN/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(13, CN, 8000);
answer();
expect(A, "8/PCMA/8000 0/PCMU/8000");
packet_seq(A, 8, PCMA_payload, 160, 1, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 160, 1, 8, PCMA_payload);
packet_seq(B, 13, "\x20", 320, 2, 8, "\xf5\x5c\x4b\xc2\xde\xf4\x5e\xd4\x47\x70\x5d\x77\x45\x51\xc5\xcd\xd7\x77\x5a\xf5\xcf\x4a\x4c\x40\xc3\x47\x74\x49\x59\xc4\x76\x57\x71\x57\x40\xc5\xf4\x5a\x47\xd6\xc4\xf6\xc7\xf3\x40\x58\x74\x54\x4b\xd7\x5c\xc7\x41\x49\xf5\x5b\x53\xd9\x70\x44\xcd\xc4\xce\xcb\xc7\x58\xcd\x45\xc6\x71\xf5\x70\x43\xca\x43\xd5\x52\x5c\x75\x74\xc6\xc3\x4f\xda\x56\xc3\x46\xf5\x49\xdf\x56\x4f\x71\x5b\x52\xc6\x4e\xd0\x43\xc2\xcd\xd5\xdf\x40\x43\x4a\xf7\xf6\xd9\xdf\xde\x45\xc9\xd9\xc2\xf0\xc1\x4a\x40\x52\xd1\x5b\xd0\x54\xc9\x5e\xde\xd5\x74\x5c\x5d\x59\x71\xc1\xc1\x71\xd2\xcb\x50\x50\x54\x53\x75\xdc\x4b\xcf\xc2\xd7\x4a\xcc\x58\xc7\xdb\xd8\x48\x4a\xd6\x58\xf0\x46");
packet_seq(A, 8, PCMA_silence, 320, 2, 13, "\x40");
end();
// CN transcoding - reverse 1
start();
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(13, CN, 8000);
c_consume(CN);
offer();
expect(B, "8/PCMA/8000 0/PCMU/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
answer();
expect(A, "8/PCMA/8000 0/PCMU/8000 13/CN/8000");
packet_seq(A, 8, PCMA_payload, 160, 1, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 160, 1, 8, PCMA_payload);
packet_seq(A, 13, "\x20", 320, 2, 8, "\xf5\x5c\x4b\xc2\xde\xf4\x5e\xd4\x47\x70\x5d\x77\x45\x51\xc5\xcd\xd7\x77\x5a\xf5\xcf\x4a\x4c\x40\xc3\x47\x74\x49\x59\xc4\x76\x57\x71\x57\x40\xc5\xf4\x5a\x47\xd6\xc4\xf6\xc7\xf3\x40\x58\x74\x54\x4b\xd7\x5c\xc7\x41\x49\xf5\x5b\x53\xd9\x70\x44\xcd\xc4\xce\xcb\xc7\x58\xcd\x45\xc6\x71\xf5\x70\x43\xca\x43\xd5\x52\x5c\x75\x74\xc6\xc3\x4f\xda\x56\xc3\x46\xf5\x49\xdf\x56\x4f\x71\x5b\x52\xc6\x4e\xd0\x43\xc2\xcd\xd5\xdf\x40\x43\x4a\xf7\xf6\xd9\xdf\xde\x45\xc9\xd9\xc2\xf0\xc1\x4a\x40\x52\xd1\x5b\xd0\x54\xc9\x5e\xde\xd5\x74\x5c\x5d\x59\x71\xc1\xc1\x71\xd2\xcb\x50\x50\x54\x53\x75\xdc\x4b\xcf\xc2\xd7\x4a\xcc\x58\xc7\xdb\xd8\x48\x4a\xd6\x58\xf0\x46");
packet_seq(B, 8, PCMA_silence, 320, 2, 13, "\x40");
end();
// CN transcoding - reverse 2
start();
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(13, CN, 8000);
c_accept(CN);
offer();
expect(B, "8/PCMA/8000 0/PCMU/8000 13/CN/8000");
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
answer();
expect(A, "8/PCMA/8000 0/PCMU/8000 13/CN/8000");
packet_seq(A, 8, PCMA_payload, 160, 1, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 160, 1, 8, PCMA_payload);
packet_seq(A, 13, "\x20", 320, 2, 8, "\xf5\x5c\x4b\xc2\xde\xf4\x5e\xd4\x47\x70\x5d\x77\x45\x51\xc5\xcd\xd7\x77\x5a\xf5\xcf\x4a\x4c\x40\xc3\x47\x74\x49\x59\xc4\x76\x57\x71\x57\x40\xc5\xf4\x5a\x47\xd6\xc4\xf6\xc7\xf3\x40\x58\x74\x54\x4b\xd7\x5c\xc7\x41\x49\xf5\x5b\x53\xd9\x70\x44\xcd\xc4\xce\xcb\xc7\x58\xcd\x45\xc6\x71\xf5\x70\x43\xca\x43\xd5\x52\x5c\x75\x74\xc6\xc3\x4f\xda\x56\xc3\x46\xf5\x49\xdf\x56\x4f\x71\x5b\x52\xc6\x4e\xd0\x43\xc2\xcd\xd5\xdf\x40\x43\x4a\xf7\xf6\xd9\xdf\xde\x45\xc9\xd9\xc2\xf0\xc1\x4a\x40\x52\xd1\x5b\xd0\x54\xc9\x5e\xde\xd5\x74\x5c\x5d\x59\x71\xc1\xc1\x71\xd2\xcb\x50\x50\x54\x53\x75\xdc\x4b\xcf\xc2\xd7\x4a\xcc\x58\xc7\xdb\xd8\x48\x4a\xd6\x58\xf0\x46");
packet_seq(B, 8, PCMA_silence, 320, 2, 13, "\x40");
end();
// DTMF PT TC
start();
sdp_pt(9, G722, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(101, telephone-event, 8000);
c_mask(all);
transcode(opus/48000/1);
transcode(PCMA);
transcode(telephone-event);
offer();
expect(B, "96/opus/48000/useinbandfec=1 8/PCMA/8000 97/telephone-event/48000/0-15 101/telephone-event/8000");
sdp_pt(96, opus, 48000);
sdp_pt(97, telephone-event, 48000);
flags.single_codec = 1;
answer();
expect(A, "9/G722/8000 101/telephone-event/8000");
packet_seq(A, 101, "\x05\x07\x01\x40", 4000, 10, 97, "\x05\x07\x07\x80");
packet_seq(B, 97, "\x05\x07\x07\x80", 4000, 10, 101, "\x05\x07\x01\x40");
end();
// DTMF PT TC w eq PT
start();
sdp_pt(96, opus, 48000);
sdp_pt(8, PCMA, 8000);
sdp_pt(102, telephone-event, 48000);
sdp_pt(101, telephone-event, 8000);
c_mask(all);
transcode(opus);
transcode(PCMA);
transcode(PCMU);
transcode(telephone-event);
offer();
expect(B, "96/opus/48000 8/PCMA/8000 0/PCMU/8000 101/telephone-event/8000 102/telephone-event/48000");
sdp_pt(0, PCMU, 8000);
sdp_pt(101, telephone-event, 8000);
flags.single_codec = 1;
answer();
expect(A, "96/opus/48000 102/telephone-event/48000");
packet_seq(A, 102, "\x05\x07\x01\x40", 4000, 10, 101, "\x05\x07\x00\x35");
packet_seq(B, 101, "\x05\x07\x07\x80", 4000, 10, 102, "\x05\x07\x2d\x00");
end();
//reusing_codecs test
start();
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(9, PCMA, 8000);
offer();
expect(A, "0/PCMU/8000 8/PCMA/8000 9/PCMA/8000");
sdp_pt(7, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
answer();
expect(B, "0/PCMU/8000 8/PCMA/8000");
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(9, PCMA, 8000);
offer();
expect(A, "0/PCMU/8000 8/PCMA/8000 9/PCMA/8000");
sdp_pt(7, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
answer();
expect(B, "0/PCMU/8000 8/PCMA/8000");
end();
start();
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(9, G722, 8000);
offer();
expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(9, G722, 8000);
answer();
expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
sdp_pt(9, G722, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
offer();
expect(A, "9/G722/8000 8/PCMA/8000 0/PCMU/8000");
expect(B, "9/G722/8000 8/PCMA/8000 0/PCMU/8000");
sdp_pt(9, G722, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
answer();
expect(A, "9/G722/8000 8/PCMA/8000 0/PCMU/8000");
expect(B, "9/G722/8000 8/PCMA/8000 0/PCMU/8000");
end();
start();
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(9, G722, 8000);
flags.reuse_codec = 1;
offer();
expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(9, G722, 8000);
flags.reuse_codec = 1;
answer();
expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
sdp_pt(9, G722, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
flags.reuse_codec = 1;
offer();
expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
sdp_pt(9, G722, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
flags.reuse_codec = 1;
answer();
expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
end();
start();
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(9, G722, 8000);
flags.reuse_codec = 1;
flags.single_codec = 1;
offer();
expect(A, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
sdp_pt(0, PCMU, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(9, G722, 8000);
flags.reuse_codec = 1;
flags.single_codec = 1;
answer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
sdp_pt(9, G722, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
flags.reuse_codec = 1;
flags.single_codec = 1;
offer();
expect(A, "0/PCMU/8000 9/G722/8000 8/PCMA/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
sdp_pt(9, G722, 8000);
sdp_pt(8, PCMA, 8000);
sdp_pt(0, PCMU, 8000);
flags.reuse_codec = 1;
flags.single_codec = 1;
answer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
end();
// media silencing PCMA
start();
sdp_pt(8, PCMA, 8000);
offer();
expect(A, "8/PCMA/8000");
expect(B, "8/PCMA/8000");
sdp_pt(8, PCMA, 8000);
answer();
expect(A, "8/PCMA/8000");
expect(B, "8/PCMA/8000");
packet_seq(A, 8, PCMA_payload, 0, 0, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 0, 0, 8, PCMA_payload);
packet_seq(A, 8, PCMA_payload, 160, 1, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 160, 1, 8, PCMA_payload);
call.silence_media = 1;
packet_seq(A, 8, PCMA_payload, 320, 2, 8, PCMA_silence);
packet_seq(B, 8, PCMA_payload, 320, 2, 8, PCMA_silence);
packet_seq(A, 8, PCMA_payload, 480, 3, 8, PCMA_silence);
packet_seq(B, 8, PCMA_payload, 480, 3, 8, PCMA_silence);
call.silence_media = 0;
packet_seq(A, 8, PCMA_payload, 640, 4, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 640, 4, 8, PCMA_payload);
packet_seq(A, 8, PCMA_payload, 800, 5, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 800, 5, 8, PCMA_payload);
ml_A->silence_media = 1;
packet_seq(A, 8, PCMA_payload, 960, 6, 8, PCMA_silence);
packet_seq(B, 8, PCMA_payload, 960, 6, 8, PCMA_payload);
packet_seq(A, 8, PCMA_payload, 1120, 7, 8, PCMA_silence);
packet_seq(B, 8, PCMA_payload, 1120, 7, 8, PCMA_payload);
ml_A->silence_media = 0;
packet_seq(A, 8, PCMA_payload, 1280, 8, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 1280, 8, 8, PCMA_payload);
packet_seq(A, 8, PCMA_payload, 1440, 9, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 1440, 9, 8, PCMA_payload);
ml_B->silence_media = 1;
packet_seq(A, 8, PCMA_payload, 1600, 10, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 1600, 10, 8, PCMA_silence);
packet_seq(A, 8, PCMA_payload, 1760, 11, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 1760, 11, 8, PCMA_silence);
ml_B->silence_media = 0;
packet_seq(A, 8, PCMA_payload, 1920, 12, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 1920, 12, 8, PCMA_payload);
packet_seq(A, 8, PCMA_payload, 2080, 13, 8, PCMA_payload);
packet_seq(B, 8, PCMA_payload, 2080, 13, 8, PCMA_payload);
end();
// media silencing PCMU
start();
sdp_pt(0, PCMU, 8000);
offer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000");
sdp_pt(0, PCMU, 8000);
answer();
expect(A, "0/PCMU/8000");
expect(B, "0/PCMU/8000");
packet_seq(A, 0, PCMU_payload, 0, 0, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 0, 0, 0, PCMU_payload);
packet_seq(A, 0, PCMU_payload, 160, 1, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 160, 1, 0, PCMU_payload);
call.silence_media = 1;
packet_seq(A, 0, PCMU_payload, 320, 2, 0, PCMU_silence);
packet_seq(B, 0, PCMU_payload, 320, 2, 0, PCMU_silence);
packet_seq(A, 0, PCMU_payload, 480, 3, 0, PCMU_silence);
packet_seq(B, 0, PCMU_payload, 480, 3, 0, PCMU_silence);
call.silence_media = 0;
packet_seq(A, 0, PCMU_payload, 640, 4, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 640, 4, 0, PCMU_payload);
packet_seq(A, 0, PCMU_payload, 800, 5, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 800, 5, 0, PCMU_payload);
ml_A->silence_media = 1;
packet_seq(A, 0, PCMU_payload, 960, 6, 0, PCMU_silence);
packet_seq(B, 0, PCMU_payload, 960, 6, 0, PCMU_payload);
packet_seq(A, 0, PCMU_payload, 1120, 7, 0, PCMU_silence);
packet_seq(B, 0, PCMU_payload, 1120, 7, 0, PCMU_payload);
ml_A->silence_media = 0;
packet_seq(A, 0, PCMU_payload, 1280, 8, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 1280, 8, 0, PCMU_payload);
packet_seq(A, 0, PCMU_payload, 1440, 9, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 1440, 9, 0, PCMU_payload);
ml_B->silence_media = 1;
packet_seq(A, 0, PCMU_payload, 1600, 10, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 1600, 10, 0, PCMU_silence);
packet_seq(A, 0, PCMU_payload, 1760, 11, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 1760, 11, 0, PCMU_silence);
ml_B->silence_media = 0;
packet_seq(A, 0, PCMU_payload, 1920, 12, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 1920, 12, 0, PCMU_payload);
packet_seq(A, 0, PCMU_payload, 2080, 13, 0, PCMU_payload);
packet_seq(B, 0, PCMU_payload, 2080, 13, 0, PCMU_payload);
end();
start();
sdp_pt_s(96, opus, 48000);
sdp_pt(8, PCMA, 8000);
c_accept(opus/48000/2);
offer();
expect(A, "96/opus/48000/2 8/PCMA/8000");
expect(B, "96/opus/48000/2 8/PCMA/8000");
sdp_pt(8, PCMA, 8000);
answer();
expect(A, "96/opus/48000/2");
expect(B, "8/PCMA/8000");
end();
start();
sdp_pt(96, opus, 48000);
sdp_pt(8, PCMA, 8000);
c_accept(opus/48000);
offer();
expect(A, "96/opus/48000 8/PCMA/8000");
expect(B, "96/opus/48000 8/PCMA/8000");
sdp_pt(8, PCMA, 8000);
answer();
expect(A, "96/opus/48000");
expect(B, "8/PCMA/8000");
end();
start();
sdp_pt(96, opus, 48000);
sdp_pt(8, PCMA, 8000);
c_accept(opus);
offer();
expect(A, "96/opus/48000 8/PCMA/8000");
expect(B, "96/opus/48000 8/PCMA/8000");
sdp_pt(8, PCMA, 8000);
answer();
expect(A, "96/opus/48000");
expect(B, "8/PCMA/8000");
end();
start();
sdp_pt_s(96, opus, 48000);
sdp_pt(8, PCMA, 8000);
c_accept(opus);
offer();
expect(A, "96/opus/48000/2 8/PCMA/8000");
expect(B, "96/opus/48000/2 8/PCMA/8000");
sdp_pt(8, PCMA, 8000);
answer();
expect(A, "96/opus/48000/2");
expect(B, "8/PCMA/8000");
end();
return 0;
}
int get_local_log_level(unsigned int u) {
return 7;
}