diff --git a/lib/codeclib.c b/lib/codeclib.c index 077eb626c..6b60e67fc 100644 --- a/lib/codeclib.c +++ b/lib/codeclib.c @@ -53,6 +53,8 @@ static format_init_f opus_init; static select_encoder_format_f opus_select_encoder_format; static select_decoder_format_f opus_select_decoder_format; static format_parse_f opus_format_parse; +static format_print_f opus_format_print; +static format_answer_f opus_format_answer; static format_parse_f ilbc_format_parse; static set_enc_options_f ilbc_set_enc_options; @@ -446,7 +448,9 @@ static struct codec_def_s __codec_defs[] = { .init = opus_init, .default_fmtp = "useinbandfec=1", .format_parse = opus_format_parse, + .format_print = opus_format_print, .format_cmp = format_cmp_ignore, + .format_answer = opus_format_answer, .select_encoder_format = opus_select_encoder_format, .select_decoder_format = opus_select_decoder_format, .dtx_methods = { @@ -2182,6 +2186,71 @@ static int opus_format_parse(struct rtp_codec_format *f, const str *fmtp) { codeclib_key_value_parse(fmtp, true, opus_parse_format_cb, &f->parsed); return 0; } +static bool opus_format_print(GString *s, const struct rtp_payload_type *p) { + if (!p->format.fmtp_parsed) + return false; + + gsize orig = s->len; + __auto_type f = &p->format.parsed.opus; + + if (f->stereo_recv) + g_string_append_printf(s, "stereo=%i; ", f->stereo_recv == -1 ? 0 : 1); + if (f->stereo_send) + g_string_append_printf(s, "sprop-stereo=%i; ", f->stereo_send == -1 ? 0 : 1); + if (f->fec_recv) + g_string_append_printf(s, "useinbandfec=%i; ", f->fec_recv == -1 ? 0 : 1); + if (f->usedtx) + g_string_append_printf(s, "usedtx=%i; ", f->usedtx == -1 ? 0 : 1); + if (f->cbr) + g_string_append_printf(s, "cbr=%i; ", f->cbr == -1 ? 0 : 1); + if (f->maxplaybackrate) + g_string_append_printf(s, "maxplaybackrate=%i; ", f->maxplaybackrate); + if (f->maxaveragebitrate) + g_string_append_printf(s, "maxaveragebitrate=%i; ", f->maxaveragebitrate); + if (f->sprop_maxcapturerate) + g_string_append_printf(s, "sprop-maxcapturerate=%i; ", f->sprop_maxcapturerate); + if (f->minptime) + g_string_append_printf(s, "minptime=%i; ", f->minptime); + + if (orig != s->len) + g_string_truncate(s, s->len - 2); + + return true; +} +static void opus_format_answer(struct rtp_payload_type *p, const struct rtp_payload_type *src) { + if (!p->format.fmtp_parsed) + return; + + __auto_type f = &p->format.parsed.opus; + + // swap send/recv + + int t = f->stereo_send; + f->stereo_send = f->stereo_recv; + f->stereo_recv = t; + + t = f->fec_send; + f->fec_send = f->fec_recv; + f->fec_recv = t; + + // if stereo recv is unset, base it on input format + if (f->stereo_recv == 0) + f->stereo_recv = src->channels == 1 ? -1 : 1; + + // we can always use FEC, unless we've been told that we should lie + if (f->fec_recv == 0) + f->fec_recv = 1; + + // set everything unsupported to 0 + f->usedtx = 0; + f->cbr = 0; + f->maxplaybackrate = 0; + f->sprop_maxcapturerate = 0; + f->maxaveragebitrate = 0; + f->minptime = 0; +} + + static int ilbc_format_parse(struct rtp_codec_format *f, const str *fmtp) { diff --git a/t/auto-daemon-tests-websocket.py b/t/auto-daemon-tests-websocket.py index e2e1fd31a..28ea4607a 100644 --- a/t/auto-daemon-tests-websocket.py +++ b/t/auto-daemon-tests-websocket.py @@ -1552,7 +1552,7 @@ class TestVideoroom(unittest.TestCase): "c=IN IP4 203.0.113.1\r\n" "a=mid:0\r\n" "a=rtpmap:111 opus/48000/2\r\n" - "a=fmtp:111 minptime=10;useinbandfec=1\r\n" + "a=fmtp:111 useinbandfec=1; minptime=10\r\n" "a=rtcp-fb:111 transport-cc\r\n" "a=recvonly\r\n" "a=rtcp:\d+\r\n" @@ -1670,7 +1670,7 @@ class TestVideoroom(unittest.TestCase): "a=ssrc:677770262 label:2de0f1b0-3a39-450e-9804-8305ec87452b\r\n" "a=mid:0\r\n" "a=rtpmap:111 opus/48000/2\r\n" - "a=fmtp:111 minptime=10;useinbandfec=1\r\n" + "a=fmtp:111 useinbandfec=1; minptime=10\r\n" "a=rtcp-fb:111 transport-cc\r\n" "a=sendonly\r\n" "a=rtcp-mux\r\n" diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index 5f3c0892c..ba4da6b82 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -1923,6 +1923,7 @@ c=IN IP4 203.0.113.1 t=0 0 m=audio PORT RTP/AVP 96 a=rtpmap:96 opus/48000/2 +a=fmtp:96 stereo=0; useinbandfec=1 a=sendrecv a=rtcp:PORT SDP @@ -1975,6 +1976,7 @@ c=IN IP4 203.0.113.1 t=0 0 m=audio PORT RTP/AVP 96 a=rtpmap:96 opus/48000/2 +a=fmtp:96 stereo=0; useinbandfec=1 a=sendrecv a=rtcp:PORT SDP @@ -2027,6 +2029,7 @@ c=IN IP4 203.0.113.1 t=0 0 m=audio PORT RTP/AVP 96 a=rtpmap:96 opus/48000/2 +a=fmtp:96 stereo=0; useinbandfec=1 a=sendrecv a=rtcp:PORT SDP @@ -2078,6 +2081,7 @@ c=IN IP4 203.0.113.1 t=0 0 m=audio PORT RTP/AVP 96 a=rtpmap:96 opus/48000/2 +a=fmtp:96 stereo=0; useinbandfec=1 a=sendrecv a=rtcp:PORT SDP @@ -2129,6 +2133,7 @@ c=IN IP4 203.0.113.1 t=0 0 m=audio PORT RTP/AVP 96 a=rtpmap:96 opus/48000/2 +a=fmtp:96 stereo=0; useinbandfec=1 a=sendrecv a=rtcp:PORT SDP @@ -8374,6 +8379,7 @@ c=IN IP4 203.0.113.1 t=0 0 m=audio PORT RTP/AVP 96 102 a=rtpmap:96 opus/48000/2 +a=fmtp:96 stereo=0; useinbandfec=1 a=rtpmap:102 telephone-event/48000 a=sendrecv a=rtcp:PORT @@ -10802,7 +10808,7 @@ t=0 0 m=audio PORT RTP/AVP 96 120 c=IN IP4 203.0.113.1 a=rtpmap:96 opus/48000/2 -a=fmtp:96 useinbandfec=1;maxplaybackrate=16000;sprop-maxcapturerate=16000;maxaveragebitrate=12000;cbr=1 +a=fmtp:96 stereo=0; useinbandfec=1 a=rtpmap:120 telephone-event/48000 a=fmtp:120 0-16 a=sendrecv @@ -10857,7 +10863,7 @@ t=0 0 m=audio PORT RTP/AVP 96 120 c=IN IP4 203.0.113.1 a=rtpmap:96 opus/48000/2 -a=fmtp:96 useinbandfec=1;maxplaybackrate=16000;sprop-maxcapturerate=16000;maxaveragebitrate=12000;cbr=1 +a=fmtp:96 stereo=0; useinbandfec=1 a=rtpmap:120 telephone-event/48000 a=fmtp:120 0-16 a=sendrecv @@ -11892,7 +11898,7 @@ a=ssrc:2628106563 mslabel:qDSKVQw0XQOFzGhek25Kn3RLxyHTM2ooxMUY a=ssrc:2628106563 label:7d669de6-65e9-4fbe-829e-e89dc4baf81c a=mid:0 a=rtpmap:111 opus/48000/2 -a=fmtp:111 minptime=10;useinbandfec=1 +a=fmtp:111 useinbandfec=1; minptime=10 a=rtcp-fb:111 transport-cc a=rtcp-fb:111 testing a=rtcp-fb:111 foobar @@ -12001,7 +12007,7 @@ a=rtcp-mux a=ssrc:97254339 cname:d7zRWvteaW9fc2Yu a=mid:0 a=rtpmap:111 opus/48000/2 -a=fmtp:111 minptime=10;useinbandfec=1 +a=fmtp:111 useinbandfec=1; minptime=10 a=rtcp-fb:111 transport-cc a=rtpmap:103 ISAC/16000 a=rtpmap:104 ISAC/32000 @@ -15787,7 +15793,7 @@ c=IN IP4 203.0.113.1 t=0 0 m=audio PORT RTP/AVP 120 a=rtpmap:120 opus/48000/2 -a=fmtp:120 useinbandfec=1; usedtx=1; maxaveragebitrate=64000 +a=fmtp:120 stereo=0; useinbandfec=1 a=sendrecv a=rtcp:PORT SDP @@ -17308,7 +17314,7 @@ m=audio PORT RTP/AVP 0 106 101 98 c=IN IP4 203.0.113.1 a=rtpmap:0 PCMU/8000 a=rtpmap:106 opus/48000/2 -a=fmtp:106 maxplaybackrate=16000; sprop-maxcapturerate=16000; minptime=20; cbr=1; maxaveragebitrate=20000; useinbandfec=1 +a=fmtp:106 useinbandfec=1; cbr=1; maxplaybackrate=16000; maxaveragebitrate=20000; sprop-maxcapturerate=16000; minptime=20 a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-16 a=rtpmap:98 telephone-event/48000