Browse code

plugin: opus: introducing new codec.

Some codec properties could be changed by rebuild
(e.g. computational complexity, use FEC, etc.). Note, that the frame size
is fixed on 20ms as the rest is not ready to get different value, eventhough
the opus RFC specifies frame size between 2,5 and 120 ms.

Michal Matyska authored on 04/03/2014 17:00:51 • Stefan Sayer committed on 24/07/2014 19:26:40
Showing 4 changed files
... ...
@@ -29,7 +29,7 @@
29 29
 #define _amci_h_
30 30
 
31 31
 /** AUDIO_BUFFER_SIZE must be a power of 2 */
32
-#define AUDIO_BUFFER_SIZE (1<<12) /* 2 KB */
32
+#define AUDIO_BUFFER_SIZE (1<<13) /* 4 KB samples */
33 33
 
34 34
 #ifdef __cplusplus
35 35
 extern "C" {
... ...
@@ -85,4 +85,6 @@
85 85
 
86 86
 #define CODEC_iSAC_WB 40
87 87
 
88
+#define CODEC_OPUS 50
89
+
88 90
 #endif
89 91
new file mode 100644
... ...
@@ -0,0 +1,8 @@
1
+COREPATH =../..
2
+
3
+plug_in_name = opus
4
+
5
+module_cflags = -I /usr/include/opus
6
+module_ldflags = -lm -fPIC -lopus
7
+
8
+include ../Makefile.audio_module
0 9
new file mode 100644
... ...
@@ -0,0 +1,246 @@
1
+/*
2
+ * Copyright (C) 2002-2003 Fhg Fokus
3
+ *
4
+ * This file is part of SEMS, a free SIP media server.
5
+ *
6
+ * SEMS is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version. This program is released under
10
+ * the GPL with the additional exemption that compiling, linking,
11
+ * and/or using OpenSSL is allowed.
12
+ *
13
+ * For a license to use the SEMS software under conditions
14
+ * other than those described here, or to purchase support for this
15
+ * software, please contact iptel.org by e-mail at the following addresses:
16
+ *    info@iptel.org
17
+ *
18
+ * SEMS is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
+ * GNU General Public License for more details.
22
+ *
23
+ * You should have received a copy of the GNU General Public License 
24
+ * along with this program; if not, write to the Free Software 
25
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
+ */
27
+
28
+#include "amci.h"
29
+#include "codecs.h" 
30
+#include "../../log.h"
31
+
32
+#include <math.h>
33
+#include <stdlib.h>
34
+#include <stdio.h>
35
+#include <string.h>
36
+/**
37
+ * @file plug-in/opus/opus.c
38
+ * OPUS support 
39
+ * This plug-in imports the OPUS Codec. 
40
+ *
41
+ * See http://www.opus-codec.org/ . 
42
+ * Features: <ul>
43
+ *           <li>OPUS codec/payload/subtype
44
+ *           <li>OPUS file format
45
+ *           </ul>
46
+ *
47
+ */
48
+
49
+#include <opus.h>
50
+
51
+#define _OPUS_APPLICATION_ OPUS_APPLICATION_VOIP
52
+/* Allowed values:
53
+OPUS_APPLICATION_VOIP                  Process signal for improved speech intelligibility.
54
+OPUS_APPLICATION_AUDIO                 Favor faithfulness to the original input.
55
+OPUS_APPLICATION_RESTRICTED_LOWDELAY   Configure the minimum possible coding delay by disabling certain modes of operation.*/
56
+
57
+#define _OPUS_MAX_BANDWIDTH_ OPUS_BANDWIDTH_FULLBAND
58
+/* Allowed values:
59
+OPUS_BANDWIDTH_NARROWBAND    -  4 kHz passband
60
+OPUS_BANDWIDTH_MEDIUMBAND    -  6 kHz passband
61
+OPUS_BANDWIDTH_WIDEBAND      -  8 kHz passband
62
+OPUS_BANDWIDTH_SUPERWIDEBAND - 12 kHz passband
63
+OPUS_BANDWIDTH_FULLBAND      - 20 kHz passband */
64
+
65
+#define _OPUS_PKT_LOSS_PCT_ 5
66
+/* Allowed values: 0 - 100 */
67
+
68
+#define _OPUS_COMPLEXITY_ 10
69
+/* Allowed values: 0 - 10, where 10 is highest computational complexity */
70
+
71
+#define _OPUS_INBAND_FEC_ 1
72
+/* Forward error correction.
73
+Allowed values: 0 - 1 */
74
+
75
+#define _OPUS_DTX_ 0
76
+/* Discontinued transmission
77
+Allowed values: 0 - 1 */
78
+
79
+static int opus_2_pcm16( unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
80
+			 unsigned int channels, unsigned int rate, long h_codec );
81
+
82
+static int opus_plc( unsigned char* out_buf, unsigned int size,
83
+		     unsigned int channels, unsigned int rate, long h_codec );
84
+
85
+static int pcm16_2_opus( unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
86
+			 unsigned int channels, unsigned int rate, long h_codec );
87
+static long opus_create(const char* format_parameters, amci_codec_fmt_info_t* format_description);
88
+static void opus_destroy(long h_inst);
89
+
90
+#if SYSTEM_SAMPLECLOCK_RATE >= 48000
91
+#define _OPUS_RATE 48000
92
+#elif SYSTEM_SAMPLECLOCK_RATE >= 24000
93
+#define _OPUS_RATE 24000
94
+#elif SYSTEM_SAMPLECLOCK_RATE >= 12000
95
+#define _OPUS_RATE 12000
96
+#elif SYSTEM_SAMPLECLOCK_RATE >=  8000
97
+#define _OPUS_RATE  8000
98
+#else
99
+#error Minimal sample rate for OPUS codec is 8000.
100
+#endif
101
+
102
+BEGIN_EXPORTS( "opus" , AMCI_NO_MODULEINIT, AMCI_NO_MODULEDESTROY )
103
+
104
+  BEGIN_CODECS
105
+    CODEC( CODEC_OPUS, pcm16_2_opus, opus_2_pcm16, opus_plc,
106
+           opus_create, 
107
+           opus_destroy,
108
+           NULL, NULL )
109
+  END_CODECS
110
+    
111
+  BEGIN_PAYLOADS
112
+    PAYLOAD( -1, "opus", _OPUS_RATE, 48000, 2, CODEC_OPUS, AMCI_PT_AUDIO_FRAME )
113
+  END_PAYLOADS
114
+
115
+  BEGIN_FILE_FORMATS
116
+  END_FILE_FORMATS
117
+
118
+END_EXPORTS
119
+
120
+typedef struct {
121
+  OpusEncoder* opus_enc;
122
+  OpusDecoder* opus_dec;
123
+} opus_state_t;
124
+
125
+long opus_create(const char* format_parameters, amci_codec_fmt_info_t* format_description) {
126
+  opus_state_t* codec_inst;
127
+  int error;
128
+ 
129
+  if (format_parameters) {
130
+    DBG("OPUS params: >>%s<<.\n", format_parameters);
131
+  } 
132
+
133
+  format_description[0].id = AMCI_FMT_FRAME_LENGTH ;
134
+  format_description[0].value = 20;
135
+  format_description[1].id = AMCI_FMT_FRAME_SIZE;
136
+  format_description[1].value = 20 * _OPUS_RATE / 1000;
137
+  format_description[2].id = 0;
138
+    
139
+  codec_inst = (opus_state_t*)malloc(sizeof(opus_state_t));
140
+
141
+  if (!codec_inst) 
142
+    return -1;
143
+
144
+  codec_inst->opus_enc = opus_encoder_create(_OPUS_RATE,1,_OPUS_APPLICATION_,&error);
145
+  if (error) {
146
+    DBG("OPUS: error %d while creating encoder state.\n", error);
147
+    return -1;
148
+  }
149
+
150
+  opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_FORCE_CHANNELS(1));
151
+  opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_MAX_BANDWIDTH(_OPUS_MAX_BANDWIDTH_));
152
+  opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_PACKET_LOSS_PERC(_OPUS_PKT_LOSS_PCT_));
153
+  opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_COMPLEXITY(_OPUS_COMPLEXITY_));
154
+  opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_INBAND_FEC(_OPUS_INBAND_FEC_));
155
+  opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_DTX(_OPUS_DTX_));
156
+
157
+  codec_inst->opus_dec = opus_decoder_create(_OPUS_RATE,1,&error);
158
+  if (error) {
159
+    DBG("OPUS: error %d while creating decoder state.\n", error);
160
+    opus_encoder_destroy(codec_inst->opus_enc);
161
+    return -1;
162
+  }
163
+
164
+  return (long)codec_inst;
165
+}
166
+
167
+void opus_destroy(long h_inst) {
168
+  opus_state_t* codec_inst;
169
+
170
+  if (h_inst) {
171
+    codec_inst = (opus_state_t*)h_inst;
172
+    opus_encoder_destroy(codec_inst->opus_enc);
173
+    opus_decoder_destroy(codec_inst->opus_dec);
174
+    free(codec_inst);
175
+  }
176
+}
177
+
178
+int pcm16_2_opus( unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
179
+		  unsigned int channels, unsigned int rate, long h_codec )
180
+{
181
+  opus_state_t* codec_inst;
182
+  int res;
183
+
184
+  if (!h_codec){
185
+    ERROR("opus codec not initialized.\n");
186
+    return 0;
187
+  }
188
+  codec_inst = (opus_state_t*)h_codec;
189
+
190
+  res = opus_encode(codec_inst->opus_enc, (opus_int16*)in_buf, size/2/channels, out_buf, AUDIO_BUFFER_SIZE);
191
+  /* returns bytes in encoded frame */
192
+
193
+  DBG ("OPUS encode: size: %d, chan: %d, rate: %d, result %d.\n", size, channels, rate, res);
194
+  return res;
195
+}
196
+
197
+static int opus_2_pcm16( unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
198
+			 unsigned int channels, unsigned int rate, long h_codec )
199
+{
200
+  opus_state_t* codec_inst;
201
+  int res;
202
+
203
+  if (!h_codec){
204
+    ERROR("opus codec not initialized.\n");
205
+    return 0;
206
+  }
207
+  codec_inst = (opus_state_t*)h_codec;
208
+
209
+  if (0<(res = opus_decode(codec_inst->opus_dec, in_buf, size, (opus_int16*)out_buf, AUDIO_BUFFER_SIZE/2, 0))) {
210
+    /* returns samples in encoded frame */
211
+    res*=2;
212
+  }
213
+
214
+  DBG ("OPUS decode: size: %d, chan: %d, rate: %d, result %d.\n", size, channels, rate, res);
215
+
216
+  return res;
217
+
218
+}
219
+
220
+static int opus_plc( unsigned char* out_buf, unsigned int size,
221
+		     unsigned int channels, unsigned int rate, long h_codec )
222
+{
223
+  opus_state_t* codec_inst;
224
+  int res;
225
+
226
+  if (!h_codec){
227
+    ERROR("opus codec not initialized.\n");
228
+    return 0;
229
+  }
230
+  codec_inst = (opus_state_t*)h_codec;
231
+
232
+  if (size/channels > AUDIO_BUFFER_SIZE) {
233
+    DBG("OPUS plc: size %d, chan %d exceeds buffer size %d.\n", size, channels, AUDIO_BUFFER_SIZE);
234
+    return 0;
235
+  }
236
+
237
+  if (0<(res = opus_decode(codec_inst->opus_dec, NULL, 0, (opus_int16*)out_buf, size/2/channels, 0))) {
238
+    /* returns samples in encoded frame */
239
+    res*=2;
240
+  }
241
+
242
+  DBG ("OPUS plc: size: %d, chan: %d, rate: %d, result %d.\n", size, channels, rate, res);
243
+
244
+  return res;
245
+}
246
+