1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 *
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <string.h>
10 #include <signal.h>
11
12 #include "uvoice_os.h"
13 #include "uvoice_types.h"
14 #include "uvoice_recorder.h"
15
16 #include "uvoice_common.h"
17 #include "uvoice_record.h"
18
19 #include "opensource/opus/source/include/opus.h"
20
21
22 #define UVOICE_OPUS_HEAD_SIZE 8
23
24
25 typedef struct {
26 void *handler;
27 short *in;
28 char *out;
29 int rate;
30 int channels;
31 } opus_encoder_t;
32
int_to_char(uint32_t i,uint8_t ch[4])33 static void int_to_char(uint32_t i, uint8_t ch[4])
34 {
35 ch[0] = i>>24;
36 ch[1] = (i>>16)&0xFF;
37 ch[2] = (i>>8)&0xFF;
38 ch[3] = i&0xFF;
39 }
40
opus_encode_process(void * priv,uint8_t * buffer,int nbytes)41 static int opus_encode_process(void *priv, uint8_t *buffer, int nbytes)
42 {
43 media_encoder_t *mencoder = (media_encoder_t *)priv;
44 opus_encoder_t *opus;
45 uint32_t enc_final_range = 0;
46 char ch[4];
47 int sample;
48 int enc_len = 0;
49 int out_len = 0;
50 int len;
51 int i;
52
53 int time_ms = os_current_time();
54
55 if (!mencoder) {
56 M_LOGE("mencoder null !\n");
57 return -1;
58 }
59
60 opus = mencoder->encoder;
61 if (!opus) {
62 M_LOGE("opus encoder null !\n");
63 return -1;
64 }
65
66 if (!opus->in) {
67 opus->in = snd_zalloc(nbytes, AFM_MAIN);
68 if (!opus->in) {
69 M_LOGE("alloc opus in failed !\n");
70 return -1;
71 }
72 }
73
74 if (!opus->out) {
75 opus->out = snd_zalloc(nbytes, AFM_MAIN);
76 if (!opus->out) {
77 M_LOGE("alloc opus out failed !\n");
78 snd_free(opus->in);
79 opus->in = NULL;
80 return -1;
81 }
82 }
83
84 for (i = 0; i < nbytes/sizeof(short); i++) {
85 sample = buffer[2 * i + 1] << 8 | buffer[2 * i];
86 opus->in[i] = ((sample & 0xffff) ^ 0x8000) - 0x8000;
87 }
88
89 while(1) {
90 len = opus_encode(opus->handler, opus->in + enc_len,
91 (nbytes - enc_len) / sizeof(short), opus->out, nbytes);
92 if (len <= 0) {
93 M_LOGE("encoder error %d !\n", len);
94 return -1;
95 }
96
97 enc_len += opus_packet_get_samples_per_frame(opus->out, opus->rate) *
98 opus_packet_get_nb_frames(opus->out, len);
99 if (enc_len == 0) {
100 M_LOGE("encoder output zero !\n");
101 break;
102 }
103
104 snd_memcpy(buffer + out_len + UVOICE_OPUS_HEAD_SIZE,
105 opus->out, len); /* playload */
106
107 int_to_char(len, ch);
108 snd_memcpy(buffer + out_len, ch, sizeof(int)); /* playload len */
109
110 opus_encoder_ctl(opus->handler, OPUS_GET_FINAL_RANGE(&enc_final_range));
111 int_to_char(enc_final_range, ch);
112 snd_memcpy(buffer + out_len + UVOICE_OPUS_HEAD_SIZE - sizeof(int),
113 ch, sizeof(int));
114
115 out_len += len + UVOICE_OPUS_HEAD_SIZE;
116
117 if (enc_len >= nbytes / sizeof(short))
118 break;
119 }
120
121 //time_ms = os_current_time() - time_ms;
122 //M_LOGD("time %dms ratio %d/%d\n", time_ms, out_len, nbytes);
123
124 return out_len;
125 }
126
opus_encode_action(void * priv,recorder_action_t action,void * arg)127 static int opus_encode_action(void *priv, recorder_action_t action, void *arg)
128 {
129 media_encoder_t *mencoder = (media_encoder_t *)priv;
130 opus_encoder_t *opus;
131 int ret;
132
133 if (!mencoder) {
134 M_LOGE("mencoder null !\n");
135 return -1;
136 }
137
138 opus = mencoder->encoder;
139 if (!opus) {
140 M_LOGE("opus encoder null !\n");
141 return -1;
142 }
143
144 if (action == RECORDER_START) {
145 int mem_size = opus_encoder_get_size(mencoder->channels);
146 if (mem_size <= 0) {
147 M_LOGE("get mem size failed %d!\n", mem_size);
148 return -1;
149 }
150
151 M_LOGD("opus mem size %d\n", mem_size);
152 opus->handler = snd_zalloc(mem_size, AFM_MAIN);
153 if (!opus->handler) {
154 M_LOGE("alloc opus mem failed !\n");
155 return -1;
156 }
157
158 ret = opus_encoder_init(opus->handler, mencoder->rate,
159 mencoder->channels, OPUS_APPLICATION_VOIP);
160 if (ret != OPUS_OK) {
161 snd_free(opus->handler);
162 opus->handler = NULL;
163 M_LOGE("opus init failed %d!\n", ret);
164 return -1;
165 }
166
167 M_LOGD("rate %d channels %d bitrate %d\n",
168 mencoder->rate,
169 mencoder->channels, mencoder->bitrate);
170
171 opus->rate = mencoder->rate;
172 opus_encoder_ctl(opus->handler, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
173 opus_encoder_ctl(opus->handler, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
174 opus_encoder_ctl(opus->handler, OPUS_SET_FORCE_CHANNELS(mencoder->channels));
175 opus_encoder_ctl(opus->handler, OPUS_SET_BITRATE(mencoder->bitrate));
176 opus_encoder_ctl(opus->handler, OPUS_SET_COMPLEXITY(1));
177 opus_encoder_ctl(opus->handler, OPUS_SET_VBR(0));
178 opus_encoder_ctl(opus->handler, OPUS_SET_PACKET_LOSS_PERC(0));
179 opus_encoder_ctl(opus->handler, OPUS_SET_LSB_DEPTH(16));
180 opus_encoder_ctl(opus->handler, OPUS_SET_INBAND_FEC(0));
181 opus_encoder_ctl(opus->handler, OPUS_SET_DTX(0));
182
183 M_LOGD("opus encoder init\n");
184 } else if (action == RECORDER_STOP) {
185 if (opus->in) {
186 snd_free(opus->in);
187 opus->in = NULL;
188 }
189 if (opus->out) {
190 snd_free(opus->out);
191 opus->out = NULL;
192 }
193 snd_free(opus->handler);
194 M_LOGD("opus encoder free\n");
195 }
196
197 return 0;
198 }
199
opus_encode_create(media_encoder_t * mencoder)200 int opus_encode_create(media_encoder_t *mencoder)
201 {
202 opus_encoder_t *opus;
203
204 if (!mencoder) {
205 M_LOGE("mencoder null !\n");
206 return -1;
207 }
208
209 opus = snd_zalloc(sizeof(opus_encoder_t), AFM_MAIN);
210 if (!opus) {
211 M_LOGE("alloc opus encoder failed !\n");
212 return -1;
213 }
214
215 mencoder->encoder = opus;
216 mencoder->encode = opus_encode_process;
217 mencoder->action = opus_encode_action;
218
219 M_LOGI("opus encoder create\n");
220 return 0;
221 }
222
opus_encode_release(media_encoder_t * mencoder)223 int opus_encode_release(media_encoder_t *mencoder)
224 {
225 opus_encoder_t *opus;
226
227 if (!mencoder) {
228 M_LOGE("mencoder null !\n");
229 return -1;
230 }
231
232 opus = mencoder->encoder;
233 if (!opus) {
234 M_LOGE("opus encoder null !\n");
235 return -1;
236 }
237
238 snd_free(opus);
239 mencoder->encoder = NULL;
240
241 M_LOGI("opus encoder release\n");
242 return 0;
243 }
244