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