1 /**
2 * @file opus.c Opus Audio Codec
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6
7 #include <re.h>
8 #include <baresip.h>
9 #include <opus/opus.h>
10 #include "opus.h"
11
12
13 /**
14 * @defgroup opus opus
15 *
16 * The OPUS audio codec
17 *
18 * Supported version: libopus 1.0.0 or later
19 *
20 * Configuration options:
21 *
22 \verbatim
23 opus_bitrate 128000 # Average bitrate in [bps]
24 opus_cbr {yes,no} # Constant Bitrate (inverse of VBR)
25 opus_inbandfec {yes,no} # Enable inband Forward Error Correction (FEC)
26 opus_dtx {yes,no} # Enable Discontinuous Transmission (DTX)
27 \endverbatim
28 *
29 * References:
30 *
31 * RFC 6716 Definition of the Opus Audio Codec
32 * RFC 7587 RTP Payload Format for the Opus Speech and Audio Codec
33 *
34 * http://opus-codec.org/downloads/
35 */
36
37
38 static bool opus_mirror;
39 static char fmtp[256] = "";
40 static char fmtp_mirror[256];
41
42
opus_fmtp_enc(struct mbuf * mb,const struct sdp_format * fmt,bool offer,void * arg)43 static int opus_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt,
44 bool offer, void *arg)
45 {
46 bool mirror;
47
48 (void)arg;
49 (void)offer;
50
51 if (!mb || !fmt)
52 return 0;
53
54 mirror = !offer && str_isset(fmtp_mirror);
55
56 return mbuf_printf(mb, "a=fmtp:%s %s\r\n",
57 fmt->id, mirror ? fmtp_mirror : fmtp);
58 }
59
60
61 static struct aucodec opus = {
62 .name = "opus",
63 .srate = 48000,
64 .crate = 48000,
65 .ch = 2,
66 .fmtp = fmtp,
67 .encupdh = opus_encode_update,
68 .ench = opus_encode_frm,
69 .decupdh = opus_decode_update,
70 .dech = opus_decode_frm,
71 .plch = opus_decode_pkloss,
72 };
73
74
opus_mirror_params(const char * x)75 void opus_mirror_params(const char *x)
76 {
77 if (!opus_mirror)
78 return;
79
80 info("opus: mirror parameters: \"%s\"\n", x);
81
82 str_ncpy(fmtp_mirror, x, sizeof(fmtp_mirror));
83 }
84
85
module_init(void)86 static int module_init(void)
87 {
88 struct conf *conf = conf_cur();
89 uint32_t value;
90 char *p = fmtp + str_len(fmtp);
91 bool b, stereo = true, sprop_stereo = true;
92 int n = 0;
93
94 conf_get_bool(conf, "opus_stereo", &stereo);
95 conf_get_bool(conf, "opus_sprop_stereo", &sprop_stereo);
96
97 /* always set stereo parameter first */
98 n = re_snprintf(p, sizeof(fmtp) - str_len(p),
99 "stereo=%d;sprop-stereo=%d", stereo, sprop_stereo);
100 if (n <= 0)
101 return ENOMEM;
102
103 p += n;
104
105 if (0 == conf_get_u32(conf, "opus_bitrate", &value)) {
106
107 n = re_snprintf(p, sizeof(fmtp) - str_len(p),
108 ";maxaveragebitrate=%d", value);
109 if (n <= 0)
110 return ENOMEM;
111
112 p += n;
113 }
114
115 if (0 == conf_get_bool(conf, "opus_cbr", &b)) {
116
117 n = re_snprintf(p, sizeof(fmtp) - str_len(p),
118 ";cbr=%d", b);
119 if (n <= 0)
120 return ENOMEM;
121
122 p += n;
123 }
124
125 if (0 == conf_get_bool(conf, "opus_inbandfec", &b)) {
126
127 n = re_snprintf(p, sizeof(fmtp) - str_len(p),
128 ";useinbandfec=%d", b);
129 if (n <= 0)
130 return ENOMEM;
131
132 p += n;
133 }
134
135 if (0 == conf_get_bool(conf, "opus_dtx", &b)) {
136
137 n = re_snprintf(p, sizeof(fmtp) - str_len(p),
138 ";usedtx=%d", b);
139 if (n <= 0)
140 return ENOMEM;
141
142 p += n;
143 }
144
145 (void)conf_get_bool(conf, "opus_mirror", &opus_mirror);
146
147 if (opus_mirror) {
148 opus.fmtp = NULL;
149 opus.fmtp_ench = opus_fmtp_enc;
150 }
151
152 debug("opus: fmtp=\"%s\"\n", fmtp);
153
154 aucodec_register(baresip_aucodecl(), &opus);
155
156 return 0;
157 }
158
159
module_close(void)160 static int module_close(void)
161 {
162 aucodec_unregister(&opus);
163
164 return 0;
165 }
166
167
168 EXPORT_SYM const struct mod_export DECL_EXPORTS(opus) = {
169 "opus",
170 "audio codec",
171 module_init,
172 module_close,
173 };
174