TT#132251 implement media silencing

Change-Id: I0902bd72e2733b96ff75bcf52856a58c51a750f6
pull/1346/head
Richard Fuchs 4 years ago
parent c2b78aa9cd
commit 413798e43f

@ -571,6 +571,8 @@ a string and determines the type of message. Currently the following commands ar
* unblock DTMF * unblock DTMF
* block media * block media
* unblock media * unblock media
* silence media
* unsilence media
* start forwarding * start forwarding
* stop forwarding * stop forwarding
* play media * play media
@ -751,9 +753,10 @@ Optionally included keys are:
- `all` - `all`
Only relevant to the `unblock media` message. Instructs *rtpengine* to remove not only a Only relevant to the `unblock media` and `unsilence media`
full-call media block, but also remove directional media blocks that were imposed on messages. Instructs *rtpengine* to remove not only a full-call
individual participants. media block, but also remove directional media blocks that were
imposed on individual participants.
- `pad crypto` - `pad crypto`
@ -1805,6 +1808,13 @@ Analogous to `block DTMF` and `unblock DTMF` but blocks media packets instead of
can still pass through when media blocking is enabled. Media packets can be blocked for an entire call, or can still pass through when media blocking is enabled. Media packets can be blocked for an entire call, or
directionally for individual participants. See `block DTMF` above for details. directionally for individual participants. See `block DTMF` above for details.
`silence media` and `unsilence media` Messages
----------------------------------------------
Identical to `block media` and `unblock media` except that media packets are
not simply blocked, but rather have their payload replaced with silence audio.
This is only supported for certain trivial audio codecs (i.e. G.711, G.722).
`start forwarding` and `stop forwarding` Messages `start forwarding` and `stop forwarding` Messages
------------------------------------------------- -------------------------------------------------

@ -2212,6 +2212,63 @@ const char *call_unblock_media_ng(bencode_item_t *input, bencode_item_t *output)
} }
const char *call_silence_media_ng(bencode_item_t *input, bencode_item_t *output) {
AUTO_CLEANUP_NULL(struct call *call, call_unlock_release);
struct call_monologue *monologue;
const char *errstr = NULL;
struct sdp_ng_flags flags;
errstr = media_block_match(&call, &monologue, &flags, input, OP_OTHER);
if (errstr)
return errstr;
if (monologue) {
ilog(LOG_INFO, "Silencing directional media (tag '" STR_FORMAT_M "')",
STR_FMT_M(&monologue->tag));
monologue->silence_media = 1;
__monologue_unkernelize(monologue);
}
else {
ilog(LOG_INFO, "Blocking media (entire call)");
call->silence_media = 1;
__call_unkernelize(call);
}
return NULL;
}
const char *call_unsilence_media_ng(bencode_item_t *input, bencode_item_t *output) {
AUTO_CLEANUP_NULL(struct call *call, call_unlock_release);
struct call_monologue *monologue;
const char *errstr = NULL;
struct sdp_ng_flags flags;
errstr = media_block_match(&call, &monologue, &flags, input, OP_OTHER);
if (errstr)
return errstr;
if (monologue) {
ilog(LOG_INFO, "Unsilencing directional media (tag '" STR_FORMAT_M "')",
STR_FMT_M(&monologue->tag));
monologue->silence_media = 0;
__monologue_unkernelize(monologue);
}
else {
ilog(LOG_INFO, "Unsilencing media (entire call)");
call->silence_media = 0;
if (flags.all) {
for (GList *l = call->monologues.head; l; l = l->next) {
monologue = l->data;
monologue->silence_media = 0;
}
}
__call_unkernelize(call);
}
return NULL;
}
#ifdef WITH_TRANSCODING #ifdef WITH_TRANSCODING
static const char *play_media_select_party(struct call **call, GQueue *monologues, static const char *play_media_select_party(struct call **call, GQueue *monologues,
bencode_item_t *input) bencode_item_t *input)

@ -1307,8 +1307,26 @@ void codec_add_raw_packet(struct media_packet *mp, unsigned int clockrate) {
} }
g_queue_push_tail(&mp->packets_out, p); g_queue_push_tail(&mp->packets_out, p);
} }
static int handler_func_passthrough(struct codec_handler *h, struct media_packet *mp) { static bool handler_silence_block(struct codec_handler *h, struct media_packet *mp) {
if (mp->call->block_media || mp->media->monologue->block_media) if (mp->call->block_media || mp->media->monologue->block_media)
return false;
if (mp->call->silence_media || mp->media->monologue->silence_media) {
if (h->source_pt.codec_def && h->source_pt.codec_def->silence_pattern.len) {
if (h->source_pt.codec_def->silence_pattern.len == 1)
memset(mp->payload.s, h->source_pt.codec_def->silence_pattern.s[0],
mp->payload.len);
else {
for (size_t pos = 0; pos < mp->payload.len;
pos += h->source_pt.codec_def->silence_pattern.len)
memcpy(&mp->payload.s[pos], h->source_pt.codec_def->silence_pattern.s,
h->source_pt.codec_def->silence_pattern.len);
}
}
}
return true;
}
static int handler_func_passthrough(struct codec_handler *h, struct media_packet *mp) {
if (!handler_silence_block(h, mp))
return 0; return 0;
if (mp->rtp) if (mp->rtp)
@ -1928,7 +1946,7 @@ void codec_init_payload_type(struct rtp_payload_type *pt, enum media_type type)
static int handler_func_passthrough_ssrc(struct codec_handler *h, struct media_packet *mp) { static int handler_func_passthrough_ssrc(struct codec_handler *h, struct media_packet *mp) {
if (G_UNLIKELY(!mp->rtp)) if (G_UNLIKELY(!mp->rtp))
return handler_func_passthrough(h, mp); return handler_func_passthrough(h, mp);
if (mp->call->block_media || mp->media->monologue->block_media) if (!handler_silence_block(h, mp))
return 0; return 0;
if (mp->rtp) if (mp->rtp)
@ -2820,7 +2838,7 @@ void codec_calc_jitter(struct ssrc_ctx *ssrc, unsigned long ts, unsigned int clo
static int handler_func_transcode(struct codec_handler *h, struct media_packet *mp) { static int handler_func_transcode(struct codec_handler *h, struct media_packet *mp) {
if (G_UNLIKELY(!mp->rtp)) if (G_UNLIKELY(!mp->rtp))
return handler_func_passthrough(h, mp); return handler_func_passthrough(h, mp);
if (mp->call->block_media || mp->media->monologue->block_media) if (!handler_silence_block(h, mp))
return 0; return 0;
// use main codec handler for supp codecs // use main codec handler for supp codecs

@ -38,13 +38,13 @@ const char *ng_command_strings[NGC_COUNT] = {
"ping", "offer", "answer", "delete", "query", "list", "start recording", "ping", "offer", "answer", "delete", "query", "list", "start recording",
"stop recording", "start forwarding", "stop forwarding", "block DTMF", "stop recording", "start forwarding", "stop forwarding", "block DTMF",
"unblock DTMF", "block media", "unblock media", "play media", "stop media", "unblock DTMF", "block media", "unblock media", "play media", "stop media",
"play DTMF", "statistics", "play DTMF", "statistics", "silence media", "unsilence media",
}; };
const char *ng_command_strings_short[NGC_COUNT] = { const char *ng_command_strings_short[NGC_COUNT] = {
"Ping", "Offer", "Answer", "Delete", "Query", "List", "StartRec", "Ping", "Offer", "Answer", "Delete", "Query", "List", "StartRec",
"StopRec", "StartFwd", "StopFwd", "BlkDTMF", "StopRec", "StartFwd", "StopFwd", "BlkDTMF",
"UnblkDTMF", "BlkMedia", "UnblkMedia", "PlayMedia", "StopMedia", "UnblkDTMF", "BlkMedia", "UnblkMedia", "PlayMedia", "StopMedia",
"PlayDTMF", "Stats", "PlayDTMF", "Stats", "SlnMedia", "UnslnMedia",
}; };
static void timeval_update_request_time(struct request_time *request, const struct timeval *offer_diff) { static void timeval_update_request_time(struct request_time *request, const struct timeval *offer_diff) {
@ -282,6 +282,14 @@ int control_ng_process(str *buf, const endpoint_t *sin, char *addr,
errstr = call_unblock_media_ng(dict, resp); errstr = call_unblock_media_ng(dict, resp);
command = NGC_UNBLOCK_MEDIA; command = NGC_UNBLOCK_MEDIA;
break; break;
case CSH_LOOKUP("silence media"):
errstr = call_silence_media_ng(dict, resp);
command = NGC_SILENCE_MEDIA;
break;
case CSH_LOOKUP("unsilence media"):
errstr = call_unsilence_media_ng(dict, resp);
command = NGC_UNSILENCE_MEDIA;
break;
case CSH_LOOKUP("play media"): case CSH_LOOKUP("play media"):
errstr = call_play_media_ng(dict, resp); errstr = call_play_media_ng(dict, resp);
command = NGC_PLAY_MEDIA; command = NGC_PLAY_MEDIA;

@ -1210,13 +1210,17 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out
rs = l->data; rs = l->data;
// only add payload types that are passthrough for all sinks // only add payload types that are passthrough for all sinks
bool can_kernelize = true; bool can_kernelize = true;
bool silenced = (call->silence_media || media->monologue->silence_media) ? true : false;
unsigned int clockrate = 0; unsigned int clockrate = 0;
str replace_pattern = STR_NULL;
for (GList *k = sinks->head; k; k = k->next) { for (GList *k = sinks->head; k; k = k->next) {
struct sink_handler *ksh = k->data; struct sink_handler *ksh = k->data;
struct packet_stream *ksink = ksh->sink; struct packet_stream *ksink = ksh->sink;
struct codec_handler *ch = codec_handler_get(media, rs->payload_type, struct codec_handler *ch = codec_handler_get(media, rs->payload_type,
ksink->media); ksink->media);
clockrate = ch->source_pt.clock_rate; clockrate = ch->source_pt.clock_rate;
if (silenced && ch->source_pt.codec_def)
replace_pattern = ch->source_pt.codec_def->silence_pattern;
if (ch->kernelize) if (ch->kernelize)
continue; continue;
can_kernelize = false; can_kernelize = false;
@ -1224,9 +1228,17 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out
} }
if (!can_kernelize) if (!can_kernelize)
continue; continue;
struct rtpengine_payload_type *rpt = &reti->payload_types[reti->num_payload_types++]; struct rtpengine_payload_type *rpt = &reti->payload_types[reti->num_payload_types++];
rpt->pt_num = rs->payload_type; rpt->pt_num = rs->payload_type;
rpt->clock_rate = clockrate; rpt->clock_rate = clockrate;
if (replace_pattern.len > sizeof(reti->payload_types->replace_pattern))
ilog(LOG_WARNING | LOG_FLAG_LIMIT, "Payload replacement pattern too long (%zu)",
replace_pattern.len);
else {
rpt->replace_pattern_len = replace_pattern.len;
memcpy(rpt->replace_pattern, replace_pattern.s, replace_pattern.len);
}
} }
g_list_free(values); g_list_free(values);
} }

@ -417,6 +417,7 @@ struct call_monologue {
unsigned int block_dtmf:1; unsigned int block_dtmf:1;
unsigned int block_media:1; unsigned int block_media:1;
unsigned int silence_media:1;
unsigned int rec_forwarding:1; unsigned int rec_forwarding:1;
unsigned int inject_dtmf:1; unsigned int inject_dtmf:1;
}; };
@ -515,6 +516,7 @@ struct call {
unsigned int block_dtmf:1; unsigned int block_dtmf:1;
unsigned int block_media:1; unsigned int block_media:1;
unsigned int silence_media:1;
unsigned int recording_on:1; unsigned int recording_on:1;
unsigned int rec_forwarding:1; unsigned int rec_forwarding:1;
unsigned int drop_traffic:1; unsigned int drop_traffic:1;

@ -170,6 +170,8 @@ const char *call_block_dtmf_ng(bencode_item_t *, bencode_item_t *);
const char *call_unblock_dtmf_ng(bencode_item_t *, bencode_item_t *); const char *call_unblock_dtmf_ng(bencode_item_t *, bencode_item_t *);
const char *call_block_media_ng(bencode_item_t *, bencode_item_t *); const char *call_block_media_ng(bencode_item_t *, bencode_item_t *);
const char *call_unblock_media_ng(bencode_item_t *, bencode_item_t *); const char *call_unblock_media_ng(bencode_item_t *, bencode_item_t *);
const char *call_silence_media_ng(bencode_item_t *, bencode_item_t *);
const char *call_unsilence_media_ng(bencode_item_t *, bencode_item_t *);
const char *call_play_media_ng(bencode_item_t *, bencode_item_t *); const char *call_play_media_ng(bencode_item_t *, bencode_item_t *);
const char *call_stop_media_ng(bencode_item_t *, bencode_item_t *); const char *call_stop_media_ng(bencode_item_t *, bencode_item_t *);
const char *call_play_dtmf_ng(bencode_item_t *, bencode_item_t *); const char *call_play_dtmf_ng(bencode_item_t *, bencode_item_t *);

@ -29,6 +29,8 @@ enum ng_command {
NGC_STOP_MEDIA, NGC_STOP_MEDIA,
NGC_PLAY_DTMF, NGC_PLAY_DTMF,
NGC_STATISTICS, NGC_STATISTICS,
NGC_SILENCE_MEDIA,
NGC_UNSILENCE_MEDIA,
NGC_COUNT // last, number of elements NGC_COUNT // last, number of elements
}; };

@ -1629,11 +1629,15 @@ static int proc_list_show(struct seq_file *f, void *v) {
(unsigned long long) atomic64_read(&g->stats.bytes), (unsigned long long) atomic64_read(&g->stats.bytes),
(unsigned long long) atomic64_read(&g->stats.packets), (unsigned long long) atomic64_read(&g->stats.packets),
(unsigned long long) atomic64_read(&g->stats.errors)); (unsigned long long) atomic64_read(&g->stats.errors));
for (i = 0; i < g->target.num_payload_types; i++) for (i = 0; i < g->target.num_payload_types; i++) {
seq_printf(f, " RTP payload type %3u: %20llu bytes, %20llu packets\n", seq_printf(f, " RTP payload type %3u: %20llu bytes, %20llu packets\n",
g->target.payload_types[i].pt_num, g->target.payload_types[i].pt_num,
(unsigned long long) atomic64_read(&g->rtp_stats[i].bytes), (unsigned long long) atomic64_read(&g->rtp_stats[i].bytes),
(unsigned long long) atomic64_read(&g->rtp_stats[i].packets)); (unsigned long long) atomic64_read(&g->rtp_stats[i].packets));
if (g->target.payload_types[i].replace_pattern_len)
seq_printf(f, " %u bytes replacement payload\n",
g->target.payload_types[i].replace_pattern_len);
}
if (g->target.ssrc) if (g->target.ssrc)
seq_printf(f, " SSRC in: %lx\n", (unsigned long) ntohl(g->target.ssrc)); seq_printf(f, " SSRC in: %lx\n", (unsigned long) ntohl(g->target.ssrc));
proc_list_crypto_print(f, &g->decrypt, &g->target.decrypt, "decryption"); proc_list_crypto_print(f, &g->decrypt, &g->target.decrypt, "decryption");
@ -4483,6 +4487,19 @@ intercept_done:
} }
no_intercept: no_intercept:
// pattern rewriting
if (rtp_pt_idx >= 0 && g->target.payload_types[rtp_pt_idx].replace_pattern_len && rtp.ok) {
if (g->target.payload_types[rtp_pt_idx].replace_pattern_len == 1)
memset(rtp.payload, g->target.payload_types[rtp_pt_idx].replace_pattern[0],
rtp.payload_len);
else {
for (i = 0; i < rtp.payload_len;
i += g->target.payload_types[rtp_pt_idx].replace_pattern_len)
memcpy(&rtp.payload[i], g->target.payload_types[rtp_pt_idx].replace_pattern,
g->target.payload_types[rtp_pt_idx].replace_pattern_len);
}
}
// output // output
for (i = 0; i < g->target.num_destinations; i++) { for (i = 0; i < g->target.num_destinations; i++) {
struct rtpengine_output *o = &g->outputs[i]; struct rtpengine_output *o = &g->outputs[i];

@ -94,7 +94,9 @@ enum rtpengine_src_mismatch {
struct rtpengine_payload_type { struct rtpengine_payload_type {
unsigned char pt_num; unsigned char pt_num;
unsigned char replace_pattern_len;
uint32_t clock_rate; uint32_t clock_rate;
char replace_pattern[16];
}; };
struct rtpengine_target_info { struct rtpengine_target_info {

@ -162,6 +162,7 @@ static codec_def_t __codec_defs[] = {
.bits_per_sample = 8, .bits_per_sample = 8,
.media_type = MT_AUDIO, .media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec, .codec_type = &codec_type_avcodec,
.silence_pattern = STR_CONST_INIT("\xd5"),
.dtx_methods = { .dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence, [DTX_SILENCE] = &dtx_method_silence,
[DTX_CN] = &dtx_method_cn, [DTX_CN] = &dtx_method_cn,
@ -178,6 +179,7 @@ static codec_def_t __codec_defs[] = {
.bits_per_sample = 8, .bits_per_sample = 8,
.media_type = MT_AUDIO, .media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec, .codec_type = &codec_type_avcodec,
.silence_pattern = STR_CONST_INIT("\xff"),
.dtx_methods = { .dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence, [DTX_SILENCE] = &dtx_method_silence,
[DTX_CN] = &dtx_method_cn, [DTX_CN] = &dtx_method_cn,
@ -210,6 +212,7 @@ static codec_def_t __codec_defs[] = {
.bits_per_sample = 8, .bits_per_sample = 8,
.media_type = MT_AUDIO, .media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec, .codec_type = &codec_type_avcodec,
.silence_pattern = STR_CONST_INIT("\xfa"),
.dtx_methods = { .dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence, [DTX_SILENCE] = &dtx_method_silence,
[DTX_CN] = &dtx_method_cn, [DTX_CN] = &dtx_method_cn,

@ -142,6 +142,7 @@ struct codec_def_s {
packetizer_f * const packetizer; packetizer_f * const packetizer;
const int bits_per_sample; const int bits_per_sample;
const enum media_type media_type; const enum media_type media_type;
const str silence_pattern;
// codec-specific callbacks // codec-specific callbacks
format_init_f *init; format_init_f *init;
@ -386,6 +387,7 @@ struct codec_def_s {
int dtmf; int dtmf;
int supplemental; int supplemental;
format_cmp_f * const format_cmp; format_cmp_f * const format_cmp;
const str silence_pattern;
}; };
struct packet_sequencer_s { struct packet_sequencer_s {
}; };

@ -372,6 +372,7 @@ static void dtmf(const char *s) {
#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 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_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 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 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 "\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 #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
@ -1575,6 +1576,98 @@ int main(void) {
expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000"); expect(B, "0/PCMU/8000 8/PCMA/8000 9/G722/8000");
end(); 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();
return 0; return 0;
} }

Loading…
Cancel
Save