1
0
mirror of https://github.com/danog/libtgvoip.git synced 2024-11-30 04:39:03 +01:00
This commit is contained in:
Grishka 2019-04-24 19:36:32 +03:00
parent a121aef1a9
commit bb25caf814
10 changed files with 78 additions and 66 deletions

View File

@ -41,7 +41,7 @@ tgvoip::OpusEncoder::OpusEncoder(MediaStreamItf *source, bool needSecondary):que
opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(1)); opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(1));
opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(1)); opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(1));
opus_encoder_ctl(enc, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE)); opus_encoder_ctl(enc, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND)); opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_AUTO));
requestedBitrate=20000; requestedBitrate=20000;
currentBitrate=0; currentBitrate=0;
running=false; running=false;
@ -59,9 +59,7 @@ tgvoip::OpusEncoder::OpusEncoder(MediaStreamItf *source, bool needSecondary):que
secondaryEncoder=opus_encoder_create(48000, 1, OPUS_APPLICATION_VOIP, NULL); secondaryEncoder=opus_encoder_create(48000, 1, OPUS_APPLICATION_VOIP, NULL);
opus_encoder_ctl(secondaryEncoder, OPUS_SET_COMPLEXITY(10)); opus_encoder_ctl(secondaryEncoder, OPUS_SET_COMPLEXITY(10));
opus_encoder_ctl(secondaryEncoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE)); opus_encoder_ctl(secondaryEncoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
//opus_encoder_ctl(secondaryEncoder, OPUS_SET_VBR(0));
opus_encoder_ctl(secondaryEncoder, OPUS_SET_BITRATE(8000)); opus_encoder_ctl(secondaryEncoder, OPUS_SET_BITRATE(8000));
opus_encoder_ctl(secondaryEncoder, OPUS_SET_BANDWIDTH(secondaryEnabledBandwidth));
}else{ }else{
secondaryEncoder=NULL; secondaryEncoder=NULL;
} }
@ -107,9 +105,11 @@ void tgvoip::OpusEncoder::Encode(int16_t* data, size_t len){
levelMeter->Update(data, len); levelMeter->Update(data, len);
if(secondaryEncoderEnabled!=wasSecondaryEncoderEnabled){ if(secondaryEncoderEnabled!=wasSecondaryEncoderEnabled){
wasSecondaryEncoderEnabled=secondaryEncoderEnabled; wasSecondaryEncoderEnabled=secondaryEncoderEnabled;
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(secondaryEncoderEnabled ? secondaryEnabledBandwidth : OPUS_BANDWIDTH_FULLBAND));
} }
int32_t r=opus_encode(enc, data, static_cast<int>(len), buffer, 4096); int32_t r=opus_encode(enc, data, static_cast<int>(len), buffer, 4096);
// int bw;
// opus_encoder_ctl(enc, OPUS_GET_BANDWIDTH(&bw));
// LOGV("Opus bandwidth: %d", bw);
if(r<=0){ if(r<=0){
LOGE("Error encoding: %d", r); LOGE("Error encoding: %d", r);
}else if(r==1){ }else if(r==1){
@ -185,27 +185,21 @@ void tgvoip::OpusEncoder::RunThread(){
if(vadMode){ if(vadMode){
if(frameHasVoice){ if(frameHasVoice){
opus_encoder_ctl(enc, OPUS_SET_BITRATE(currentBitrate)); opus_encoder_ctl(enc, OPUS_SET_BITRATE(currentBitrate));
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(vadModeVoiceBandwidth));
if(secondaryEncoder){ if(secondaryEncoder){
opus_encoder_ctl(secondaryEncoder, OPUS_SET_BITRATE(currentBitrate)); opus_encoder_ctl(secondaryEncoder, OPUS_SET_BITRATE(currentBitrate));
opus_encoder_ctl(secondaryEncoder, OPUS_SET_BANDWIDTH(vadModeVoiceBandwidth));
} }
}else{ }else{
opus_encoder_ctl(enc, OPUS_SET_BITRATE(vadNoVoiceBitrate)); opus_encoder_ctl(enc, OPUS_SET_BITRATE(vadNoVoiceBitrate));
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(vadModeNoVoiceBandwidth));
if(secondaryEncoder){ if(secondaryEncoder){
opus_encoder_ctl(secondaryEncoder, OPUS_SET_BITRATE(vadNoVoiceBitrate)); opus_encoder_ctl(secondaryEncoder, OPUS_SET_BITRATE(vadNoVoiceBitrate));
opus_encoder_ctl(secondaryEncoder, OPUS_SET_BANDWIDTH(vadModeNoVoiceBandwidth));
} }
} }
wasVadMode=true; wasVadMode=true;
}else if(wasVadMode){ }else if(wasVadMode){
wasVadMode=false; wasVadMode=false;
opus_encoder_ctl(enc, OPUS_SET_BITRATE(currentBitrate)); opus_encoder_ctl(enc, OPUS_SET_BITRATE(currentBitrate));
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(secondaryEncoderEnabled ? secondaryEnabledBandwidth : OPUS_AUTO));
if(secondaryEncoder){ if(secondaryEncoder){
opus_encoder_ctl(secondaryEncoder, OPUS_SET_BITRATE(currentBitrate)); opus_encoder_ctl(secondaryEncoder, OPUS_SET_BITRATE(currentBitrate));
opus_encoder_ctl(secondaryEncoder, OPUS_SET_BANDWIDTH(secondaryEnabledBandwidth));
} }
} }
Encode(frame, 960*packetsPerFrame); Encode(frame, 960*packetsPerFrame);

View File

@ -3303,7 +3303,7 @@ void VoIPController::SendPacketReliably(unsigned char type, unsigned char *data,
void VoIPController::SendExtra(Buffer &data, unsigned char type){ void VoIPController::SendExtra(Buffer &data, unsigned char type){
ENFORCE_MSG_THREAD; ENFORCE_MSG_THREAD;
LOGV("Sending extra type %u length %lu", type, (unsigned int)data.Length()); LOGV("Sending extra type %u length %u", type, (unsigned int)data.Length());
for(vector<UnacknowledgedExtraData>::iterator x=currentExtras.begin();x!=currentExtras.end();++x){ for(vector<UnacknowledgedExtraData>::iterator x=currentExtras.begin();x!=currentExtras.end();++x){
if(x->type==type){ if(x->type==type){
x->firstContainingSeq=0; x->firstContainingSeq=0;

View File

@ -532,6 +532,10 @@ namespace tgvoip {
((video::VideoSourceAndroid*)(intptr_t)inst)->SetRotation((unsigned int)rotation); ((video::VideoSourceAndroid*)(intptr_t)inst)->SetRotation((unsigned int)rotation);
} }
void VideoSource_nativeSetPaused(JNIEnv* env, jobject thiz, jlong inst, jboolean paused){
((video::VideoSourceAndroid*)(intptr_t)inst)->SetStreamPaused((bool)paused);
}
#pragma mark - VideoRenderer #pragma mark - VideoRenderer
jlong VideoRenderer_nativeInit(JNIEnv* env, jobject thiz){ jlong VideoRenderer_nativeInit(JNIEnv* env, jobject thiz){
@ -612,7 +616,7 @@ extern "C" void tgvoipRegisterNatives(JNIEnv* env){
if(videoRenderer){ if(videoRenderer){
video::VideoRendererAndroid::decodeAndDisplayMethod=env->GetMethodID(videoRenderer, "decodeAndDisplay", "(Ljava/nio/ByteBuffer;IJ)V"); video::VideoRendererAndroid::decodeAndDisplayMethod=env->GetMethodID(videoRenderer, "decodeAndDisplay", "(Ljava/nio/ByteBuffer;IJ)V");
video::VideoRendererAndroid::resetMethod=env->GetMethodID(videoRenderer, "reset", "(Ljava/lang/String;II[[B)V"); video::VideoRendererAndroid::resetMethod=env->GetMethodID(videoRenderer, "reset", "(Ljava/lang/String;II[[B)V");
video::VideoRendererAndroid::setStreamEnabledMethod=env->GetMethodID(videoRenderer, "setStreamEnabled", "(Z)V"); video::VideoRendererAndroid::setStreamEnabledMethod=env->GetMethodID(videoRenderer, "setStreamEnabled", "(ZZ)V");
video::VideoRendererAndroid::setRotationMethod=env->GetMethodID(videoRenderer, "setRotation", "(I)V"); video::VideoRendererAndroid::setRotationMethod=env->GetMethodID(videoRenderer, "setRotation", "(I)V");
} }
} }
@ -713,7 +717,8 @@ extern "C" void tgvoipRegisterNatives(JNIEnv* env){
{"nativeRelease", "(J)V", (void *) &tgvoip::VideoSource_nativeRelease}, {"nativeRelease", "(J)V", (void *) &tgvoip::VideoSource_nativeRelease},
{"nativeSetVideoStreamParameters", "(J[Ljava/nio/ByteBuffer;II)V", (void *) &tgvoip::VideoSource_nativeSetVideoStreamParameters}, {"nativeSetVideoStreamParameters", "(J[Ljava/nio/ByteBuffer;II)V", (void *) &tgvoip::VideoSource_nativeSetVideoStreamParameters},
{"nativeSendFrame", "(JLjava/nio/ByteBuffer;III)V", (void *) &tgvoip::VideoSource_nativeSendFrame}, {"nativeSendFrame", "(JLjava/nio/ByteBuffer;III)V", (void *) &tgvoip::VideoSource_nativeSendFrame},
{"nativeSetRotation", "(JI)V", (void*)&tgvoip::VideoSource_nativeSetRotation} {"nativeSetRotation", "(JI)V", (void*)&tgvoip::VideoSource_nativeSetRotation},
{"nativeSetPaused", "(JZ)V", (void*)&tgvoip::VideoSource_nativeSetPaused}
}; };
env->RegisterNatives(videoSource, videoSourceMethods, sizeof(videoSourceMethods)/sizeof(JNINativeMethod)); env->RegisterNatives(videoSource, videoSourceMethods, sizeof(videoSourceMethods)/sizeof(JNINativeMethod));
} }

View File

@ -127,7 +127,7 @@ void VideoRendererAndroid::RunThread(){
} }
env->CallVoidMethod(jobj, resetMethod, env->NewStringUTF(codecStr.c_str()), (jint)width, (jint)height, jcsd); env->CallVoidMethod(jobj, resetMethod, env->NewStringUTF(codecStr.c_str()), (jint)width, (jint)height, jcsd);
}else if(request.type==Request::Type::UpdateStreamState){ }else if(request.type==Request::Type::UpdateStreamState){
env->CallVoidMethod(jobj, setStreamEnabledMethod, streamEnabled); env->CallVoidMethod(jobj, setStreamEnabledMethod, streamEnabled, streamPaused);
} }
} }
free(buf); free(buf);
@ -150,5 +150,10 @@ void VideoRendererAndroid::SetRotation(uint16_t rotation){
} }
void VideoRendererAndroid::SetStreamPaused(bool paused){ void VideoRendererAndroid::SetStreamPaused(bool paused){
streamPaused=paused;
Request req{
Buffer(0),
Request::Type::UpdateStreamState
};
queue.Put(std::move(req));
} }

View File

@ -49,6 +49,7 @@ namespace tgvoip{
int width; int width;
int height; int height;
bool streamEnabled=true; bool streamEnabled=true;
bool streamPaused=false;
uint32_t codec; uint32_t codec;
uint16_t rotation=0; uint16_t rotation=0;
jobject jobj; jobject jobj;

View File

@ -86,3 +86,7 @@ void VideoSourceAndroid::SetBitrate(uint32_t bitrate){
env->CallVoidMethod(javaObject, setBitrateMethod, (jint)bitrate); env->CallVoidMethod(javaObject, setBitrateMethod, (jint)bitrate);
}); });
} }
void VideoSourceAndroid::SetStreamPaused(bool paused){
streamStateCallback(paused);
}

View File

@ -23,6 +23,7 @@ namespace tgvoip{
void SetStreamParameters(std::vector<Buffer> csd, unsigned int width, unsigned int height); void SetStreamParameters(std::vector<Buffer> csd, unsigned int width, unsigned int height);
virtual void RequestKeyFrame() override; virtual void RequestKeyFrame() override;
virtual void SetBitrate(uint32_t bitrate) override; virtual void SetBitrate(uint32_t bitrate) override;
void SetStreamPaused(bool paused);
static std::vector<uint32_t> availableEncoders; static std::vector<uint32_t> availableEncoders;
private: private:

View File

@ -12,28 +12,28 @@ using namespace tgvoip;
using namespace tgvoip::video; using namespace tgvoip::video;
namespace{ namespace{
/*static*/ constexpr float QDELAY_TARGET_LO=0.1f; // seconds constexpr float QDELAY_TARGET_LO=0.1f; // seconds
/*static*/ constexpr float QDELAY_TARGET_HI=0.4f; // seconds constexpr float QDELAY_TARGET_HI=0.4f; // seconds
/*static*/ constexpr float QDELAY_WEIGHT=0.1f; constexpr float QDELAY_WEIGHT=0.1f;
/*static*/ constexpr float QDELAY_TREND_TH=0.2f; constexpr float QDELAY_TREND_TH=0.2f;
/*static*/ constexpr uint32_t MIN_CWND=3000; // bytes constexpr uint32_t MIN_CWND=3000; // bytes
/*static*/ constexpr float MAX_BYTES_IN_FLIGHT_HEAD_ROOM=1.1f; constexpr float MAX_BYTES_IN_FLIGHT_HEAD_ROOM=1.1f;
/*static*/ constexpr float GAIN=1.0f; constexpr float GAIN=1.0f;
/*static*/ constexpr float BETA_LOSS=0.9f; constexpr float BETA_LOSS=0.9f;
/*static*/ constexpr float BETA_ECN=0.9f; constexpr float BETA_ECN=0.9f;
/*static*/ constexpr float BETA_R=0.9f; constexpr float BETA_R=0.9f;
/*static*/ constexpr uint32_t MSS=1024; constexpr uint32_t MSS=1024;
/*static*/ constexpr float RATE_ADJUST_INTERVAL=0.2f; constexpr float RATE_ADJUST_INTERVAL=0.2f;
/*static*/ constexpr uint32_t TARGET_BITRATE_MIN=50*1024; // bps constexpr uint32_t TARGET_BITRATE_MIN=50*1024; // bps
/*static*/ constexpr uint32_t TARGET_BITRATE_MAX=500*1024; // bps constexpr uint32_t TARGET_BITRATE_MAX=500*1024; // bps
/*static*/ constexpr uint32_t RAMP_UP_SPEED=200000; // bps/s constexpr uint32_t RAMP_UP_SPEED=1024*1024;//200000; // bps/s
/*static*/ constexpr float PRE_CONGESTION_GUARD=0.1f; constexpr float PRE_CONGESTION_GUARD=0.1f;
/*static*/ constexpr float TX_QUEUE_SIZE_FACTOR=1.0f; constexpr float TX_QUEUE_SIZE_FACTOR=1.0f;
/*static*/ constexpr float RTP_QDELAY_TH=0.02f; // seconds constexpr float RTP_QDELAY_TH=0.02f; // seconds
/*static*/ constexpr float TARGET_RATE_SCALE_RTP_QDELAY=0.95f; constexpr float TARGET_RATE_SCALE_RTP_QDELAY=0.95f;
/*static*/ constexpr float QDELAY_TREND_LO=0.2f; constexpr float QDELAY_TREND_LO=0.2f;
/*static*/ constexpr float T_RESUME_FAST_INCREASE=5.0f; // seconds constexpr float T_RESUME_FAST_INCREASE=5.0f; // seconds
/*static*/ constexpr uint32_t RATE_PACE_MIN=50000; // bps constexpr uint32_t RATE_PACE_MIN=50000; // bps
} }
ScreamCongestionController::ScreamCongestionController() : qdelayTarget(QDELAY_TARGET_LO), cwnd(MIN_CWND) { ScreamCongestionController::ScreamCongestionController() : qdelayTarget(QDELAY_TARGET_LO), cwnd(MIN_CWND) {
@ -71,7 +71,7 @@ void ScreamCongestionController::UpdateCWnd(float qdelay){
inFastIncrease=false; inFastIncrease=false;
}else{ }else{
if((float)bytesInFlight*1.5f+bytesNewlyAcked>cwnd){ if((float)bytesInFlight*1.5f+bytesNewlyAcked>cwnd){
LOGD("HERE"); //LOGD("HERE");
cwnd+=bytesNewlyAcked; cwnd+=bytesNewlyAcked;
} }
return; return;

View File

@ -94,6 +94,7 @@ void VideoPacketSender::SetSource(VideoSource *source){
if(!source) if(!source)
return; return;
sourceChangeTime=lastVideoResolutionChangeTime=VoIPController::GetCurrentTime();
uint32_t bitrate=videoCongestionControl.GetBitrate(); uint32_t bitrate=videoCongestionControl.GetBitrate();
currentVideoBitrate=bitrate; currentVideoBitrate=bitrate;
source->SetBitrate(bitrate); source->SetBitrate(bitrate);
@ -102,9 +103,10 @@ void VideoPacketSender::SetSource(VideoSource *source){
source->SetCallback(std::bind(&VideoPacketSender::SendFrame, this, placeholders::_1, placeholders::_2, placeholders::_3)); source->SetCallback(std::bind(&VideoPacketSender::SendFrame, this, placeholders::_1, placeholders::_2, placeholders::_3));
source->SetStreamStateCallback([this](bool paused){ source->SetStreamStateCallback([this](bool paused){
stm->paused=paused; stm->paused=paused;
SendStreamFlags(*stm); GetMessageThread().Post([this]{
SendStreamFlags(*stm);
});
}); });
lastVideoResolutionChangeTime=VoIPController::GetCurrentTime();
} }
void VideoPacketSender::SendFrame(const Buffer &_frame, uint32_t flags, uint32_t rotation){ void VideoPacketSender::SendFrame(const Buffer &_frame, uint32_t flags, uint32_t rotation){
@ -125,7 +127,7 @@ void VideoPacketSender::SendFrame(const Buffer &_frame, uint32_t flags, uint32_t
source->SetBitrate(bitrate); source->SetBitrate(bitrate);
} }
int resolutionFromBitrate=GetVideoResolutionForCurrentBitrate(); int resolutionFromBitrate=GetVideoResolutionForCurrentBitrate();
if(resolutionFromBitrate!=stm->resolution && currentTime-lastVideoResolutionChangeTime>3.0){ if(resolutionFromBitrate!=stm->resolution && currentTime-lastVideoResolutionChangeTime>3.0 && currentTime-sourceChangeTime>10.0){
LOGI("Changing video resolution: %d -> %d", stm->resolution, resolutionFromBitrate); LOGI("Changing video resolution: %d -> %d", stm->resolution, resolutionFromBitrate);
stm->resolution=resolutionFromBitrate; stm->resolution=resolutionFromBitrate;
GetMessageThread().Post([this, resolutionFromBitrate]{ GetMessageThread().Post([this, resolutionFromBitrate]{
@ -291,33 +293,33 @@ void VideoPacketSender::SendFrame(const Buffer &_frame, uint32_t flags, uint32_t
int VideoPacketSender::GetVideoResolutionForCurrentBitrate(){ int VideoPacketSender::GetVideoResolutionForCurrentBitrate(){
int peerMaxVideoResolution=GetProtocolInfo().maxVideoResolution; int peerMaxVideoResolution=GetProtocolInfo().maxVideoResolution;
int resolutionFromBitrate=INIT_VIDEO_RES_1080; int resolutionFromBitrate=INIT_VIDEO_RES_1080;
// TODO: probably move this to server config if(VoIPController::GetCurrentTime()-sourceChangeTime<10.0){
if(stm->codec==CODEC_AVC || stm->codec==CODEC_VP8){ // TODO: probably move this to server config
if(currentVideoBitrate>400000){ if(stm->codec==CODEC_AVC || stm->codec==CODEC_VP8){
resolutionFromBitrate=INIT_VIDEO_RES_720; if(currentVideoBitrate>400000){
}else if(currentVideoBitrate>250000){ resolutionFromBitrate=INIT_VIDEO_RES_720;
resolutionFromBitrate=INIT_VIDEO_RES_480; }else if(currentVideoBitrate>250000){
}else{ resolutionFromBitrate=INIT_VIDEO_RES_480;
resolutionFromBitrate=INIT_VIDEO_RES_360; }else{
resolutionFromBitrate=INIT_VIDEO_RES_360;
}
}else if(stm->codec==CODEC_HEVC || stm->codec==CODEC_VP9){
if(currentVideoBitrate>400000){
resolutionFromBitrate=INIT_VIDEO_RES_1080;
}else if(currentVideoBitrate>250000){
resolutionFromBitrate=INIT_VIDEO_RES_720;
}else if(currentVideoBitrate>100000){
resolutionFromBitrate=INIT_VIDEO_RES_480;
}else{
resolutionFromBitrate=INIT_VIDEO_RES_360;
}
} }
}else if(stm->codec==CODEC_HEVC || stm->codec==CODEC_VP9){ }else{
if(currentVideoBitrate>400000){ if(stm->codec==CODEC_AVC || stm->codec==CODEC_VP8)
resolutionFromBitrate=INIT_VIDEO_RES_720;
else if(stm->codec==CODEC_HEVC || stm->codec==CODEC_VP9)
resolutionFromBitrate=INIT_VIDEO_RES_1080; resolutionFromBitrate=INIT_VIDEO_RES_1080;
}else if(currentVideoBitrate>250000){
resolutionFromBitrate=INIT_VIDEO_RES_720;
}else if(currentVideoBitrate>100000){
resolutionFromBitrate=INIT_VIDEO_RES_480;
}else{
resolutionFromBitrate=INIT_VIDEO_RES_360;
}
} }
return std::min(peerMaxVideoResolution, resolutionFromBitrate); return std::min(peerMaxVideoResolution, resolutionFromBitrate);
} }
void VideoPacketSender::SendStreamCSD(){
assert(stm->csdIsValid);
//SendExtra(buf, EXTRA_TYPE_STREAM_CSD);
}

View File

@ -42,7 +42,6 @@ namespace tgvoip{
void SendFrame(const Buffer& frame, uint32_t flags, uint32_t rotation); void SendFrame(const Buffer& frame, uint32_t flags, uint32_t rotation);
int GetVideoResolutionForCurrentBitrate(); int GetVideoResolutionForCurrentBitrate();
void SendStreamCSD();
VideoSource* source=NULL; VideoSource* source=NULL;
std::shared_ptr<VoIPController::Stream> stm; std::shared_ptr<VoIPController::Stream> stm;
@ -55,6 +54,7 @@ namespace tgvoip{
uint32_t videoPacketLossCount=0; uint32_t videoPacketLossCount=0;
uint32_t currentVideoBitrate=0; uint32_t currentVideoBitrate=0;
double lastVideoResolutionChangeTime=0.0; double lastVideoResolutionChangeTime=0.0;
double sourceChangeTime=0.0;
std::vector<Buffer> packetsForFEC; std::vector<Buffer> packetsForFEC;
size_t fecFrameCount=0; size_t fecFrameCount=0;