mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-01-10 22:57:47 +00:00
2.0-alpha4
This commit is contained in:
331
OpusDecoder.cpp
331
OpusDecoder.cpp
@@ -10,32 +10,49 @@
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "VoIPController.h"
|
||||
|
||||
#define PACKET_SIZE (960*2)
|
||||
|
||||
using namespace tgvoip;
|
||||
|
||||
tgvoip::OpusDecoder::OpusDecoder(MediaStreamItf *dst) : semaphore(32, 0){
|
||||
//this->source=source;
|
||||
tgvoip::OpusDecoder::OpusDecoder(MediaStreamItf *dst, bool isAsync){
|
||||
async=isAsync;
|
||||
dst->SetCallback(OpusDecoder::Callback, this);
|
||||
if(async){
|
||||
decodedQueue=new BlockingQueue<unsigned char*>(33);
|
||||
bufferPool=new BufferPool(PACKET_SIZE, 32);
|
||||
semaphore=new Semaphore(32, 0);
|
||||
}else{
|
||||
decodedQueue=NULL;
|
||||
bufferPool=NULL;
|
||||
semaphore=NULL;
|
||||
}
|
||||
dec=opus_decoder_create(48000, 1, NULL);
|
||||
//test=fopen("/sdcard/test.raw", "wb");
|
||||
buffer=(unsigned char *) malloc(8192);
|
||||
//lastDecoded=(unsigned char*) malloc(960*2);
|
||||
lastDecoded=NULL;
|
||||
lastDecodedLen=0;
|
||||
outputBufferSize=0;
|
||||
lastDecodedOffset=0;
|
||||
decodedQueue=new BlockingQueue<unsigned char*>(33);
|
||||
bufferPool=new BufferPool(PACKET_SIZE, 32);
|
||||
echoCanceller=NULL;
|
||||
frameDuration=20;
|
||||
consecutiveLostPackets=0;
|
||||
enableDTX=false;
|
||||
silentPacketCount=0;
|
||||
levelMeter=NULL;
|
||||
nextLen=0;
|
||||
running=false;
|
||||
remainingDataLen=0;
|
||||
processedBuffer=NULL;
|
||||
}
|
||||
|
||||
tgvoip::OpusDecoder::~OpusDecoder(){
|
||||
opus_decoder_destroy(dec);
|
||||
free(buffer);
|
||||
delete bufferPool;
|
||||
delete decodedQueue;
|
||||
if(bufferPool)
|
||||
delete bufferPool;
|
||||
if(decodedQueue)
|
||||
delete decodedQueue;
|
||||
if(semaphore)
|
||||
delete semaphore;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,215 +61,177 @@ void tgvoip::OpusDecoder::SetEchoCanceller(EchoCanceller* canceller){
|
||||
}
|
||||
|
||||
size_t tgvoip::OpusDecoder::Callback(unsigned char *data, size_t len, void *param){
|
||||
((OpusDecoder*)param)->HandleCallback(data, len);
|
||||
return 0;
|
||||
return ((OpusDecoder*)param)->HandleCallback(data, len);
|
||||
}
|
||||
|
||||
void tgvoip::OpusDecoder::HandleCallback(unsigned char *data, size_t len){
|
||||
if(!running){
|
||||
memset(data, 0, len);
|
||||
return;
|
||||
}
|
||||
if(outputBufferSize==0){
|
||||
outputBufferSize=len;
|
||||
int packetsNeeded;
|
||||
if(len>PACKET_SIZE)
|
||||
packetsNeeded=len/PACKET_SIZE;
|
||||
else
|
||||
packetsNeeded=1;
|
||||
packetsNeeded*=2;
|
||||
semaphore.Release(packetsNeeded);
|
||||
}
|
||||
assert(outputBufferSize==len && "output buffer size is supposed to be the same throughout callbacks");
|
||||
if(len>PACKET_SIZE){
|
||||
int count=len/PACKET_SIZE;
|
||||
int i;
|
||||
for(i=0;i<count;i++){
|
||||
lastDecoded=(unsigned char*) decodedQueue->GetBlocking();
|
||||
if(!lastDecoded)
|
||||
return;
|
||||
memcpy(data+(i*PACKET_SIZE), lastDecoded, PACKET_SIZE);
|
||||
if(echoCanceller)
|
||||
echoCanceller->SpeakerOutCallback(data, PACKET_SIZE);
|
||||
bufferPool->Reuse(lastDecoded);
|
||||
size_t tgvoip::OpusDecoder::HandleCallback(unsigned char *data, size_t len){
|
||||
if(async){
|
||||
if(!running){
|
||||
memset(data, 0, len);
|
||||
return 0;
|
||||
}
|
||||
semaphore.Release(count);
|
||||
}else if(len==PACKET_SIZE){
|
||||
lastDecoded=(unsigned char*) decodedQueue->GetBlocking();
|
||||
if(!lastDecoded)
|
||||
return;
|
||||
memcpy(data, lastDecoded, PACKET_SIZE);
|
||||
bufferPool->Reuse(lastDecoded);
|
||||
semaphore.Release();
|
||||
lock_mutex(mutex);
|
||||
if(echoCanceller)
|
||||
echoCanceller->SpeakerOutCallback(data, PACKET_SIZE);
|
||||
unlock_mutex(mutex);
|
||||
}else if(len<PACKET_SIZE){
|
||||
if(lastDecodedOffset==0){
|
||||
lastDecoded=(unsigned char*) decodedQueue->GetBlocking();
|
||||
}
|
||||
if(!lastDecoded)
|
||||
return;
|
||||
|
||||
memcpy(data, lastDecoded+lastDecodedOffset, len);
|
||||
lastDecodedOffset+=len;
|
||||
|
||||
if(lastDecodedOffset>=PACKET_SIZE){
|
||||
if(echoCanceller)
|
||||
echoCanceller->SpeakerOutCallback(lastDecoded, PACKET_SIZE);
|
||||
lastDecodedOffset=0;
|
||||
bufferPool->Reuse(lastDecoded);
|
||||
//LOGV("before req packet, qsize=%d", decodedQueue->Size());
|
||||
if(decodedQueue->Size()==0)
|
||||
semaphore.Release(2);
|
||||
if(outputBufferSize==0){
|
||||
outputBufferSize=len;
|
||||
int packetsNeeded;
|
||||
if(len>PACKET_SIZE)
|
||||
packetsNeeded=len/PACKET_SIZE;
|
||||
else
|
||||
semaphore.Release();
|
||||
}
|
||||
}
|
||||
/*if(lastDecodedLen){
|
||||
LOGV("ldl=%d, l=%d", lastDecodedLen, len);
|
||||
if(len==PACKET_SIZE){
|
||||
memcpy(data, lastDecoded, len);
|
||||
packetsNeeded=1;
|
||||
}else if(len>PACKET_SIZE){
|
||||
memcpy(data, lastDecoded, len);
|
||||
//LOGV("ldl=%d, l=%d", lastDecodedLen, len);
|
||||
packetsNeeded=len/PACKET_SIZE;
|
||||
}else if(len<PACKET_SIZE){
|
||||
memcpy(data, lastDecoded+lastDecodedOffset, len);
|
||||
lastDecodedOffset+=len;
|
||||
if(lastDecodedOffset>=PACKET_SIZE){
|
||||
packetsNeeded=1;
|
||||
lastDecodedOffset=0;
|
||||
packetsNeeded*=2;
|
||||
semaphore->Release(packetsNeeded);
|
||||
}
|
||||
assert(outputBufferSize==len && "output buffer size is supposed to be the same throughout callbacks");
|
||||
if(len==PACKET_SIZE){
|
||||
lastDecoded=(unsigned char *) decodedQueue->GetBlocking();
|
||||
if(!lastDecoded)
|
||||
return 0;
|
||||
memcpy(data, lastDecoded, PACKET_SIZE);
|
||||
bufferPool->Reuse(lastDecoded);
|
||||
semaphore->Release();
|
||||
if(silentPacketCount>0){
|
||||
silentPacketCount--;
|
||||
if(levelMeter)
|
||||
levelMeter->Update(reinterpret_cast<int16_t *>(data), 0);
|
||||
return 0;
|
||||
}
|
||||
if(echoCanceller){
|
||||
echoCanceller->SpeakerOutCallback(data, PACKET_SIZE);
|
||||
}
|
||||
}else{
|
||||
LOGE("Opus decoder buffer length != 960 samples");
|
||||
abort();
|
||||
}
|
||||
}else{
|
||||
LOGW("skipping callback");
|
||||
if(len>PACKET_SIZE)
|
||||
packetsNeeded=len/PACKET_SIZE;
|
||||
else
|
||||
packetsNeeded=1;
|
||||
}*/
|
||||
/*if(packetsNeeded>0){
|
||||
lock_mutex(mutex);
|
||||
notify_lock(lock);
|
||||
unlock_mutex(mutex);
|
||||
}*/
|
||||
if(remainingDataLen==0 && silentPacketCount==0){
|
||||
int duration=DecodeNextFrame();
|
||||
remainingDataLen=(size_t) (duration/20*960*2);
|
||||
}
|
||||
if(silentPacketCount>0 || remainingDataLen==0 || !processedBuffer){
|
||||
if(silentPacketCount>0)
|
||||
silentPacketCount--;
|
||||
memset(data, 0, 960*2);
|
||||
if(levelMeter)
|
||||
levelMeter->Update(reinterpret_cast<int16_t *>(data), 0);
|
||||
return 0;
|
||||
}
|
||||
memcpy(data, processedBuffer, 960*2);
|
||||
remainingDataLen-=960*2;
|
||||
if(remainingDataLen>0){
|
||||
memmove(processedBuffer, processedBuffer+960*2, remainingDataLen);
|
||||
}
|
||||
}
|
||||
if(levelMeter)
|
||||
levelMeter->Update(reinterpret_cast<int16_t *>(data), len/2);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void tgvoip::OpusDecoder::Start(){
|
||||
init_mutex(mutex);
|
||||
if(!async)
|
||||
return;
|
||||
running=true;
|
||||
start_thread(thread, OpusDecoder::StartThread, this);
|
||||
set_thread_priority(thread, get_thread_max_priority());
|
||||
set_thread_name(thread, "opus_decoder");
|
||||
thread=new Thread(new MethodPointer<tgvoip::OpusDecoder>(&tgvoip::OpusDecoder::RunThread, this), NULL);
|
||||
thread->SetName("opus_decoder");
|
||||
thread->SetMaxPriority();
|
||||
thread->Start();
|
||||
}
|
||||
|
||||
void tgvoip::OpusDecoder::Stop(){
|
||||
if(!running)
|
||||
if(!running || !async)
|
||||
return;
|
||||
running=false;
|
||||
semaphore.Release();
|
||||
join_thread(thread);
|
||||
free_mutex(mutex);
|
||||
semaphore->Release();
|
||||
thread->Join();
|
||||
delete thread;
|
||||
}
|
||||
|
||||
|
||||
void* tgvoip::OpusDecoder::StartThread(void *param){
|
||||
((tgvoip::OpusDecoder*)param)->RunThread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void tgvoip::OpusDecoder::RunThread(){
|
||||
unsigned char nextBuffer[8192];
|
||||
unsigned char decodeBuffer[8192];
|
||||
void tgvoip::OpusDecoder::RunThread(void* param){
|
||||
int i;
|
||||
int packetsPerFrame=frameDuration/20;
|
||||
bool first=true;
|
||||
LOGI("decoder: packets per frame %d", packetsPerFrame);
|
||||
size_t nextLen=0;
|
||||
while(running){
|
||||
//LOGV("after wait, running=%d", running);
|
||||
//LOGD("Will get %d packets", packetsNeeded);
|
||||
//lastDecodedLen=0;
|
||||
memcpy(buffer, nextBuffer, nextLen);
|
||||
size_t inLen=nextLen;
|
||||
//nextLen=InvokeCallback(nextBuffer, 8192);
|
||||
int playbackDuration=0;
|
||||
nextLen=jitterBuffer->HandleOutput(nextBuffer, 8192, 0, &playbackDuration);
|
||||
if(first){
|
||||
first=false;
|
||||
continue;
|
||||
}
|
||||
//LOGV("Before decode, len=%d", inLen);
|
||||
if(!inLen){
|
||||
LOGV("Trying to recover late packet");
|
||||
inLen=jitterBuffer->HandleOutput(buffer, 8192, -2, &playbackDuration);
|
||||
if(inLen)
|
||||
LOGV("Decoding late packet");
|
||||
}
|
||||
int size;
|
||||
if(inLen || nextLen)
|
||||
size=opus_decode(dec, inLen ? buffer : nextBuffer, inLen ? inLen : nextLen, (opus_int16*) decodeBuffer, packetsPerFrame*960, inLen ? 0 : 1);
|
||||
else{ // do packet loss concealment
|
||||
size=opus_decode(dec, NULL, 0, (opus_int16 *) decodeBuffer, packetsPerFrame*960, 0);
|
||||
LOGV("PLC");
|
||||
}
|
||||
if(size<0)
|
||||
LOGW("decoder: opus_decode error %d", size);
|
||||
//LOGV("After decode, size=%d", size);
|
||||
//LOGD("playbackDuration=%d", playbackDuration);
|
||||
unsigned char* processedBuffer;
|
||||
if(playbackDuration==80){
|
||||
processedBuffer=buffer;
|
||||
audio::Resampler::Rescale60To80((int16_t*) decodeBuffer, (int16_t*) processedBuffer);
|
||||
}else if(playbackDuration==40){
|
||||
processedBuffer=buffer;
|
||||
audio::Resampler::Rescale60To40((int16_t*) decodeBuffer, (int16_t*) processedBuffer);
|
||||
}else{
|
||||
processedBuffer=decodeBuffer;
|
||||
}
|
||||
for(i=0;i</*packetsPerFrame*/ playbackDuration/20;i++){
|
||||
semaphore.Acquire();
|
||||
int playbackDuration=DecodeNextFrame();
|
||||
for(i=0;i<playbackDuration/20;i++){
|
||||
semaphore->Acquire();
|
||||
if(!running){
|
||||
LOGI("==== decoder exiting ====");
|
||||
return;
|
||||
}
|
||||
unsigned char *buf=bufferPool->Get();
|
||||
if(buf){
|
||||
if(size>0){
|
||||
if(remainingDataLen>0){
|
||||
for(std::vector<AudioEffect*>::iterator effect=postProcEffects.begin();effect!=postProcEffects.end();++effect){
|
||||
(*effect)->Process(reinterpret_cast<int16_t*>(processedBuffer+(PACKET_SIZE*i)), 960);
|
||||
}
|
||||
memcpy(buf, processedBuffer+(PACKET_SIZE*i), PACKET_SIZE);
|
||||
}else{
|
||||
LOGE("Error decoding, result=%d", size);
|
||||
//LOGE("Error decoding, result=%d", size);
|
||||
memset(buf, 0, PACKET_SIZE);
|
||||
}
|
||||
decodedQueue->Put(buf);
|
||||
}else{
|
||||
LOGW("decoder: no buffers left!");
|
||||
}
|
||||
//LOGD("packets needed: %d", packetsNeeded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int tgvoip::OpusDecoder::DecodeNextFrame(){
|
||||
/*memcpy(buffer, nextBuffer, nextLen);
|
||||
size_t inLen=nextLen;
|
||||
int playbackDuration=0;
|
||||
nextLen=jitterBuffer->HandleOutput(nextBuffer, 8192, 0, &playbackDuration);
|
||||
if(first){
|
||||
first=false;
|
||||
return 0;
|
||||
}
|
||||
if(!inLen){
|
||||
LOGV("Trying to recover late packet");
|
||||
inLen=jitterBuffer->HandleOutput(buffer, 8192, -2, &playbackDuration);
|
||||
if(inLen)
|
||||
LOGV("Decoding late packet");
|
||||
}*/
|
||||
int playbackDuration=0;
|
||||
size_t len=jitterBuffer->HandleOutput(buffer, 8192, 0, true, &playbackDuration);
|
||||
bool fec=false;
|
||||
if(!len){
|
||||
fec=true;
|
||||
len=jitterBuffer->HandleOutput(buffer, 8192, 0, false, &playbackDuration);
|
||||
if(len)
|
||||
LOGV("Trying FEC...");
|
||||
}
|
||||
int size;
|
||||
if(len){
|
||||
size=opus_decode(dec, buffer, len, (opus_int16 *) decodeBuffer, packetsPerFrame*960, fec ? 1 : 0);
|
||||
consecutiveLostPackets=0;
|
||||
}else{ // do packet loss concealment
|
||||
consecutiveLostPackets++;
|
||||
if(consecutiveLostPackets>2 && enableDTX){
|
||||
silentPacketCount+=packetsPerFrame;
|
||||
size=packetsPerFrame*960;
|
||||
}else{
|
||||
size=opus_decode(dec, NULL, 0, (opus_int16 *) decodeBuffer, packetsPerFrame*960, 0);
|
||||
//LOGV("PLC");
|
||||
}
|
||||
}
|
||||
if(size<0)
|
||||
LOGW("decoder: opus_decode error %d", size);
|
||||
remainingDataLen=size;
|
||||
if(playbackDuration==80){
|
||||
processedBuffer=buffer;
|
||||
audio::Resampler::Rescale60To80((int16_t*) decodeBuffer, (int16_t*) processedBuffer);
|
||||
}else if(playbackDuration==40){
|
||||
processedBuffer=buffer;
|
||||
audio::Resampler::Rescale60To40((int16_t*) decodeBuffer, (int16_t*) processedBuffer);
|
||||
}else{
|
||||
processedBuffer=decodeBuffer;
|
||||
}
|
||||
return playbackDuration;
|
||||
}
|
||||
|
||||
|
||||
void tgvoip::OpusDecoder::SetFrameDuration(uint32_t duration){
|
||||
frameDuration=duration;
|
||||
}
|
||||
|
||||
|
||||
void tgvoip::OpusDecoder::ResetQueue(){
|
||||
/*lock_mutex(mutex);
|
||||
packetsNeeded=0;
|
||||
unlock_mutex(mutex);
|
||||
while(decodedQueue->Size()>0){
|
||||
bufferPool->Reuse((unsigned char *) decodedQueue->Get());
|
||||
}*/
|
||||
packetsPerFrame=frameDuration/20;
|
||||
}
|
||||
|
||||
|
||||
@@ -260,6 +239,14 @@ void tgvoip::OpusDecoder::SetJitterBuffer(JitterBuffer* jitterBuffer){
|
||||
this->jitterBuffer=jitterBuffer;
|
||||
}
|
||||
|
||||
void tgvoip::OpusDecoder::SetDTX(bool enable){
|
||||
enableDTX=enable;
|
||||
}
|
||||
|
||||
void tgvoip::OpusDecoder::SetLevelMeter(AudioLevelMeter *levelMeter){
|
||||
this->levelMeter=levelMeter;
|
||||
}
|
||||
|
||||
void tgvoip::OpusDecoder::AddAudioEffect(AudioEffect *effect){
|
||||
postProcEffects.push_back(effect);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user