From 08701819da38f4f8d1cbbfc19a6bd579c9a5d853 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Mon, 11 Jul 2022 08:55:48 -0400 Subject: [PATCH] TT#185100 support setting opus encoding complexity Change-Id: I8c1b9c93df2f2de5d8e4e282f3e728d8163aa4b5 --- README.md | 11 +- lib/codeclib.c | 9 +- t/auto-daemon-tests.pl | 415 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 432 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1d6b8ad31..7ad009ac9 100644 --- a/README.md +++ b/README.md @@ -1340,8 +1340,15 @@ Optionally included keys are: channels) must also be specified. Additional options that can be appended to the codec string with additional slashes - are ptime, the `fmtp` string, and additional codec-specific options, for example - `iLBC/8000/1///mode=30` to use as `fmtp`. + are ptime, the `fmtp` string, and additional codec-specific options. For example + `iLBC/8000/1///mode=30` to use `mode=30` as `fmtp` string. + + For Opus, the string of codec-specific options is passed + directly to ffmpeg, so all ffmpeg codec options can be set. Use + space, colon, semicolon, or comma to separate individual + options. For example to set the encoding complexity (also known + as compression level by ffmpeg): + `opus/48000/2////compression_level=2` If a literal `=` cannot be used due to parsing constraints (i.e. being wrongly interpreted as a key-value pair), it can be escaped by using two dashes instead, diff --git a/lib/codeclib.c b/lib/codeclib.c index a777a22a9..9f8ccb2c6 100644 --- a/lib/codeclib.c +++ b/lib/codeclib.c @@ -1647,7 +1647,14 @@ static void opus_init(struct rtp_payload_type *pt) { static void opus_set_enc_options(encoder_t *enc, const str *fmtp, const str *codec_opts) { if (enc->ptime > 0) codeclib_set_av_opt_int(enc, "frame_duration", enc->ptime); - // XXX additional opus options + + // our string might not be null terminated + char *s = g_strdup_printf(STR_FORMAT, STR_FMT(codec_opts)); + int ret = av_opt_set_from_string(enc->u.avc.avcctx, s, NULL, "=", ":; ,"); + if (ret < 0) + ilog(LOG_WARN, "Failed to set ffmpeg option string '%s' for codec '%s': %s", + s, enc->def->rtpname, av_error(ret)); + free(s); } static int ilbc_mode(int ptime, const str *fmtp, const char *direction) { diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index 7a72325ba..4744c1313 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -78,6 +78,421 @@ sub stun_succ { }; + +if ($amr_tests) { + +# opus encoder options tests + +($sock_a, $sock_b) = new_call([qw(198.51.100.16 6000)], [qw(198.51.100.16 6002)]); + +($port_a) = offer('opus encoder control, forward tc', + { codec => { transcode => ['opus/48000/2'] } }, < { transcode => ['opus/48000/2/16000'] } }, < { transcode => ['opus/48000/2////compression_level=2'] } }, < { transcode => ['opus/48000/2/16000///compression_level=2'] } }, < { transcode => ['PCMA'] } }, < { transcode => ['PCMA'], set => ['opus/48000/2/16000'] } }, < { transcode => ['PCMA'], set => ['opus/48000/2////compression_level=2'] } }, < { transcode => ['PCMA'], set => ['opus/48000/2/16000///compression_level=2'] } }, <