1 //
2 // libtgvoip is free and unencumbered public domain software.
3 // For more information, see http://unlicense.org or the UNLICENSE file
4 // you should have received with this source code distribution.
5 //
6 
7 #include "OpusEncoder.h"
8 #include <assert.h>
9 #include <algorithm>
10 #include "logging.h"
11 #include "VoIPServerConfig.h"
12 #if TGVOIP_INCLUDE_OPUS_PACKAGE
13 #include <opus/opus.h>
14 #else
15 #include <opus.h>
16 #endif
17 
18 namespace{
serverConfigValueToBandwidth(int config)19 	int serverConfigValueToBandwidth(int config){
20 		switch(config){
21 			case 0:
22 				return OPUS_BANDWIDTH_NARROWBAND;
23 			case 1:
24 				return OPUS_BANDWIDTH_MEDIUMBAND;
25 			case 2:
26 				return OPUS_BANDWIDTH_WIDEBAND;
27 			case 3:
28 				return OPUS_BANDWIDTH_SUPERWIDEBAND;
29 			case 4:
30 			default:
31 				return OPUS_BANDWIDTH_FULLBAND;
32 		}
33 	}
34 }
35 
OpusEncoder(MediaStreamItf * source,bool needSecondary)36 tgvoip::OpusEncoder::OpusEncoder(MediaStreamItf *source, bool needSecondary):queue(11), bufferPool(960*2, 10){
37 	this->source=source;
38 	source->SetCallback(tgvoip::OpusEncoder::Callback, this);
39 	enc=opus_encoder_create(48000, 1, OPUS_APPLICATION_VOIP, NULL);
40 	opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(10));
41 	opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(1));
42 	opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(1));
43 	opus_encoder_ctl(enc, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
44 	opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
45 	requestedBitrate=20000;
46 	currentBitrate=0;
47 	running=false;
48 	echoCanceller=NULL;
49 	complexity=10;
50 	frameDuration=20;
51 	levelMeter=NULL;
52 	vadNoVoiceBitrate=static_cast<uint32_t>(ServerConfig::GetSharedInstance()->GetInt("audio_vad_no_voice_bitrate", 6000));
53 	vadModeVoiceBandwidth=serverConfigValueToBandwidth(ServerConfig::GetSharedInstance()->GetInt("audio_vad_bandwidth", 3));
54 	vadModeNoVoiceBandwidth=serverConfigValueToBandwidth(ServerConfig::GetSharedInstance()->GetInt("audio_vad_no_voice_bandwidth", 0));
55 	secondaryEnabledBandwidth=serverConfigValueToBandwidth(ServerConfig::GetSharedInstance()->GetInt("audio_extra_ec_bandwidth", 2));
56 	secondaryEncoderEnabled=false;
57 
58 	if(needSecondary){
59 		secondaryEncoder=opus_encoder_create(48000, 1, OPUS_APPLICATION_VOIP, NULL);
60 		opus_encoder_ctl(secondaryEncoder, OPUS_SET_COMPLEXITY(10));
61 		opus_encoder_ctl(secondaryEncoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
62 		//opus_encoder_ctl(secondaryEncoder, OPUS_SET_VBR(0));
63 		opus_encoder_ctl(secondaryEncoder, OPUS_SET_BITRATE(8000));
64 		opus_encoder_ctl(secondaryEncoder, OPUS_SET_BANDWIDTH(secondaryEnabledBandwidth));
65 	}else{
66 		secondaryEncoder=NULL;
67 	}
68 }
69 
~OpusEncoder()70 tgvoip::OpusEncoder::~OpusEncoder(){
71 	opus_encoder_destroy(enc);
72 	if(secondaryEncoder)
73 		opus_encoder_destroy(secondaryEncoder);
74 }
75 
Start()76 void tgvoip::OpusEncoder::Start(){
77 	if(running)
78 		return;
79 	running=true;
80 	thread=new Thread(std::bind(&tgvoip::OpusEncoder::RunThread, this));
81 	thread->SetName("OpusEncoder");
82 	thread->Start();
83 	thread->SetMaxPriority();
84 }
85 
Stop()86 void tgvoip::OpusEncoder::Stop(){
87 	if(!running)
88 		return;
89 	running=false;
90 	queue.Put(NULL);
91 	thread->Join();
92 	delete thread;
93 }
94 
95 
SetBitrate(uint32_t bitrate)96 void tgvoip::OpusEncoder::SetBitrate(uint32_t bitrate){
97 	requestedBitrate=bitrate;
98 }
99 
Encode(int16_t * data,size_t len)100 void tgvoip::OpusEncoder::Encode(int16_t* data, size_t len){
101 	if(requestedBitrate!=currentBitrate){
102 		opus_encoder_ctl(enc, OPUS_SET_BITRATE(requestedBitrate));
103 		currentBitrate=requestedBitrate;
104 		LOGV("opus_encoder: setting bitrate to %u", currentBitrate);
105 	}
106 	if(levelMeter)
107 		levelMeter->Update(data, len);
108 	if(secondaryEncoderEnabled!=wasSecondaryEncoderEnabled){
109 		wasSecondaryEncoderEnabled=secondaryEncoderEnabled;
110 		opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(secondaryEncoderEnabled ? secondaryEnabledBandwidth : OPUS_BANDWIDTH_FULLBAND));
111 	}
112 	int32_t r=opus_encode(enc, data, static_cast<int>(len), buffer, 4096);
113 	if(r<=0){
114 		LOGE("Error encoding: %d", r);
115 	}else if(r==1){
116 		LOGW("DTX");
117 	}else if(running){
118 		//LOGV("Packet size = %d", r);
119 		int32_t secondaryLen=0;
120 		unsigned char secondaryBuffer[128];
121 		if(secondaryEncoderEnabled && secondaryEncoder){
122 			secondaryLen=opus_encode(secondaryEncoder, data, static_cast<int>(len), secondaryBuffer, sizeof(secondaryBuffer));
123 			//LOGV("secondaryLen %d", secondaryLen);
124 		}
125 		InvokeCallback(buffer, (size_t)r, secondaryBuffer, (size_t)secondaryLen);
126 	}
127 }
128 
Callback(unsigned char * data,size_t len,void * param)129 size_t tgvoip::OpusEncoder::Callback(unsigned char *data, size_t len, void* param){
130 	OpusEncoder* e=(OpusEncoder*)param;
131 	unsigned char* buf=e->bufferPool.Get();
132 	if(buf){
133 		assert(len==960*2);
134 		memcpy(buf, data, 960*2);
135 		e->queue.Put(buf);
136 	}else{
137 		LOGW("opus_encoder: no buffer slots left");
138 		if(e->complexity>1){
139 			e->complexity--;
140 			opus_encoder_ctl(e->enc, OPUS_SET_COMPLEXITY(e->complexity));
141 		}
142 	}
143 	return 0;
144 }
145 
146 
GetBitrate()147 uint32_t tgvoip::OpusEncoder::GetBitrate(){
148 	return requestedBitrate;
149 }
150 
SetEchoCanceller(EchoCanceller * aec)151 void tgvoip::OpusEncoder::SetEchoCanceller(EchoCanceller* aec){
152 	echoCanceller=aec;
153 }
154 
RunThread()155 void tgvoip::OpusEncoder::RunThread(){
156 	uint32_t bufferedCount=0;
157 	uint32_t packetsPerFrame=frameDuration/20;
158 	LOGV("starting encoder, packets per frame=%d", packetsPerFrame);
159 	int16_t* frame;
160 	if(packetsPerFrame>1)
161 		frame=(int16_t*) malloc(960*2*packetsPerFrame);
162 	else
163 		frame=NULL;
164 	bool frameHasVoice=false;
165 	bool wasVadMode=false;
166 	while(running){
167 		int16_t* packet=(int16_t*)queue.GetBlocking();
168 		if(packet){
169 			bool hasVoice=true;
170 			if(echoCanceller)
171 				echoCanceller->ProcessInput(packet, 960, hasVoice);
172 			if(!postProcEffects.empty()){
173 				for(effects::AudioEffect* effect:postProcEffects){
174 					effect->Process(packet, 960);
175 				}
176 			}
177 			if(packetsPerFrame==1){
178 				Encode(packet, 960);
179 			}else{
180 				memcpy(frame+(960*bufferedCount), packet, 960*2);
181     			frameHasVoice=frameHasVoice || hasVoice;
182 				bufferedCount++;
183 				if(bufferedCount==packetsPerFrame){
184 					if(vadMode){
185 						if(frameHasVoice){
186 							opus_encoder_ctl(enc, OPUS_SET_BITRATE(currentBitrate));
187 							opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(vadModeVoiceBandwidth));
188 							if(secondaryEncoder){
189 								opus_encoder_ctl(secondaryEncoder, OPUS_SET_BITRATE(currentBitrate));
190 								opus_encoder_ctl(secondaryEncoder, OPUS_SET_BANDWIDTH(vadModeVoiceBandwidth));
191 							}
192 						}else{
193 							opus_encoder_ctl(enc, OPUS_SET_BITRATE(vadNoVoiceBitrate));
194 							opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(vadModeNoVoiceBandwidth));
195 							if(secondaryEncoder){
196 								opus_encoder_ctl(secondaryEncoder, OPUS_SET_BITRATE(vadNoVoiceBitrate));
197 								opus_encoder_ctl(secondaryEncoder, OPUS_SET_BANDWIDTH(vadModeNoVoiceBandwidth));
198 							}
199 						}
200 						wasVadMode=true;
201 					}else if(wasVadMode){
202 						wasVadMode=false;
203 						opus_encoder_ctl(enc, OPUS_SET_BITRATE(currentBitrate));
204 						opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(secondaryEncoderEnabled ? secondaryEnabledBandwidth : OPUS_AUTO));
205 						if(secondaryEncoder){
206 							opus_encoder_ctl(secondaryEncoder, OPUS_SET_BITRATE(currentBitrate));
207 							opus_encoder_ctl(secondaryEncoder, OPUS_SET_BANDWIDTH(secondaryEnabledBandwidth));
208 						}
209 					}
210 					Encode(frame, 960*packetsPerFrame);
211 					bufferedCount=0;
212 					frameHasVoice=false;
213 				}
214 			}
215 			bufferPool.Reuse(reinterpret_cast<unsigned char *>(packet));
216 		}
217 	}
218 	if(frame)
219 		free(frame);
220 }
221 
222 
SetOutputFrameDuration(uint32_t duration)223 void tgvoip::OpusEncoder::SetOutputFrameDuration(uint32_t duration){
224 	frameDuration=duration;
225 }
226 
227 
SetPacketLoss(int percent)228 void tgvoip::OpusEncoder::SetPacketLoss(int percent){
229 	packetLossPercent=std::min(20, percent);
230 	opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packetLossPercent));
231 	opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(percent>0 && !secondaryEncoderEnabled ? 1 : 0));
232 }
233 
GetPacketLoss()234 int tgvoip::OpusEncoder::GetPacketLoss(){
235 	return packetLossPercent;
236 }
237 
SetDTX(bool enable)238 void tgvoip::OpusEncoder::SetDTX(bool enable){
239 	opus_encoder_ctl(enc, OPUS_SET_DTX(enable ? 1 : 0));
240 }
241 
SetLevelMeter(tgvoip::AudioLevelMeter * levelMeter)242 void tgvoip::OpusEncoder::SetLevelMeter(tgvoip::AudioLevelMeter *levelMeter){
243 	this->levelMeter=levelMeter;
244 }
245 
SetCallback(void (* f)(unsigned char *,size_t,unsigned char *,size_t,void *),void * param)246 void tgvoip::OpusEncoder::SetCallback(void (*f)(unsigned char *, size_t, unsigned char *, size_t, void *), void *param){
247 	callback=f;
248 	callbackParam=param;
249 }
250 
InvokeCallback(unsigned char * data,size_t length,unsigned char * secondaryData,size_t secondaryLength)251 void tgvoip::OpusEncoder::InvokeCallback(unsigned char *data, size_t length, unsigned char *secondaryData, size_t secondaryLength){
252 	callback(data, length, secondaryData, secondaryLength, callbackParam);
253 }
254 
SetSecondaryEncoderEnabled(bool enabled)255 void tgvoip::OpusEncoder::SetSecondaryEncoderEnabled(bool enabled){
256 	secondaryEncoderEnabled=enabled;
257 }
258 
SetVadMode(bool vad)259 void tgvoip::OpusEncoder::SetVadMode(bool vad){
260 	vadMode=vad;
261 }
AddAudioEffect(effects::AudioEffect * effect)262 void tgvoip::OpusEncoder::AddAudioEffect(effects::AudioEffect *effect){
263 	postProcEffects.push_back(effect);
264 }
265 
RemoveAudioEffect(effects::AudioEffect * effect)266 void tgvoip::OpusEncoder::RemoveAudioEffect(effects::AudioEffect *effect){
267 	std::vector<effects::AudioEffect*>::iterator i=std::find(postProcEffects.begin(), postProcEffects.end(), effect);
268 	if(i!=postProcEffects.end())
269 		postProcEffects.erase(i);
270 }
271