Display target bitrates in connection details UI
This commit is contained in:
parent
1b157a20ab
commit
e205743f0c
|
@ -260,6 +260,10 @@ public class Dino.PeerState : Object {
|
||||||
ret.audio_codec = audio_content_parameter.agreed_payload_type.name;
|
ret.audio_codec = audio_content_parameter.agreed_payload_type.name;
|
||||||
ret.audio_clockrate = audio_content_parameter.agreed_payload_type.clockrate;
|
ret.audio_clockrate = audio_content_parameter.agreed_payload_type.clockrate;
|
||||||
}
|
}
|
||||||
|
if (audio_content_parameter.stream != null && audio_content_parameter.stream.remb_enabled) {
|
||||||
|
ret.audio_target_receive_bitrate = audio_content_parameter.stream.target_receive_bitrate;
|
||||||
|
ret.audio_target_send_bitrate = audio_content_parameter.stream.target_send_bitrate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audio_content != null) {
|
if (audio_content != null) {
|
||||||
|
@ -278,6 +282,10 @@ public class Dino.PeerState : Object {
|
||||||
if (video_content_parameter.agreed_payload_type != null) {
|
if (video_content_parameter.agreed_payload_type != null) {
|
||||||
ret.video_codec = video_content_parameter.agreed_payload_type.name;
|
ret.video_codec = video_content_parameter.agreed_payload_type.name;
|
||||||
}
|
}
|
||||||
|
if (video_content_parameter.stream != null && video_content_parameter.stream.remb_enabled) {
|
||||||
|
ret.video_target_receive_bitrate = video_content_parameter.stream.target_receive_bitrate;
|
||||||
|
ret.video_target_send_bitrate = video_content_parameter.stream.target_send_bitrate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (video_content != null) {
|
if (video_content != null) {
|
||||||
|
@ -443,6 +451,8 @@ public class Dino.PeerInfo {
|
||||||
public ulong? audio_bytes_received { get; set; default=0; }
|
public ulong? audio_bytes_received { get; set; default=0; }
|
||||||
public string? audio_codec { get; set; }
|
public string? audio_codec { get; set; }
|
||||||
public uint32 audio_clockrate { get; set; }
|
public uint32 audio_clockrate { get; set; }
|
||||||
|
public uint audio_target_receive_bitrate { get; set; default=0; }
|
||||||
|
public uint audio_target_send_bitrate { get; set; default=0; }
|
||||||
|
|
||||||
public bool video_content_exists { get; set; }
|
public bool video_content_exists { get; set; }
|
||||||
public bool video_rtp_ready { get; set; }
|
public bool video_rtp_ready { get; set; }
|
||||||
|
@ -450,4 +460,6 @@ public class Dino.PeerInfo {
|
||||||
public ulong? video_bytes_sent { get; set; default=0; }
|
public ulong? video_bytes_sent { get; set; default=0; }
|
||||||
public ulong? video_bytes_received { get; set; default=0; }
|
public ulong? video_bytes_received { get; set; default=0; }
|
||||||
public string? video_codec { get; set; }
|
public string? video_codec { get; set; }
|
||||||
|
public uint video_target_receive_bitrate { get; set; default=0; }
|
||||||
|
public uint video_target_send_bitrate { get; set; default=0; }
|
||||||
}
|
}
|
|
@ -8,15 +8,19 @@ namespace Dino.Ui {
|
||||||
|
|
||||||
public Label audio_rtp_ready = new Label("?") { xalign=0, visible=true };
|
public Label audio_rtp_ready = new Label("?") { xalign=0, visible=true };
|
||||||
public Label audio_rtcp_ready = new Label("?") { xalign=0, visible=true };
|
public Label audio_rtcp_ready = new Label("?") { xalign=0, visible=true };
|
||||||
public Label audio_sent_bps = new Label("?") { xalign=0, visible=true };
|
public Label audio_sent_bps = new Label("?") { use_markup=true, xalign=0, visible=true };
|
||||||
public Label audio_recv_bps = new Label("?") { xalign=0, visible=true };
|
public Label audio_recv_bps = new Label("?") { use_markup=true, xalign=0, visible=true };
|
||||||
public Label audio_codec = new Label("?") { xalign=0, visible=true };
|
public Label audio_codec = new Label("?") { xalign=0, visible=true };
|
||||||
|
public Label audio_target_receive_bitrate = new Label("n/a") { xalign=0, visible=true };
|
||||||
|
public Label audio_target_send_bitrate = new Label("n/a") { xalign=0, visible=true };
|
||||||
|
|
||||||
public Label video_rtp_ready = new Label("") { xalign=0, visible=true };
|
public Label video_rtp_ready = new Label("") { xalign=0, visible=true };
|
||||||
public Label video_rtcp_ready = new Label("") { xalign=0, visible=true };
|
public Label video_rtcp_ready = new Label("") { xalign=0, visible=true };
|
||||||
public Label video_sent_bps = new Label("") { xalign=0, visible=true };
|
public Label video_sent_bps = new Label("") { use_markup=true, xalign=0, visible=true };
|
||||||
public Label video_recv_bps = new Label("") { xalign=0, visible=true };
|
public Label video_recv_bps = new Label("") { use_markup=true, xalign=0, visible=true };
|
||||||
public Label video_codec = new Label("") { xalign=0, visible=true };
|
public Label video_codec = new Label("") { xalign=0, visible=true };
|
||||||
|
public Label video_target_receive_bitrate = new Label("n/a") { xalign=0, visible=true };
|
||||||
|
public Label video_target_send_bitrate = new Label("n/a") { xalign=0, visible=true };
|
||||||
|
|
||||||
private int row_at = 0;
|
private int row_at = 0;
|
||||||
private bool video_added = false;
|
private bool video_added = false;
|
||||||
|
@ -34,6 +38,10 @@ namespace Dino.Ui {
|
||||||
grid.attach(audio_recv_bps, 1, row_at++, 1, 1);
|
grid.attach(audio_recv_bps, 1, row_at++, 1, 1);
|
||||||
put_row("Codec");
|
put_row("Codec");
|
||||||
grid.attach(audio_codec, 1, row_at++, 1, 1);
|
grid.attach(audio_codec, 1, row_at++, 1, 1);
|
||||||
|
put_row("Target receive bitrate");
|
||||||
|
grid.attach(audio_target_receive_bitrate, 1, row_at++, 1, 1);
|
||||||
|
put_row("Target send bitrate");
|
||||||
|
grid.attach(audio_target_send_bitrate, 1, row_at++, 1, 1);
|
||||||
|
|
||||||
this.child = grid;
|
this.child = grid;
|
||||||
}
|
}
|
||||||
|
@ -46,18 +54,26 @@ namespace Dino.Ui {
|
||||||
audio_rtp_ready.label = peer_info.audio_rtp_ready.to_string();
|
audio_rtp_ready.label = peer_info.audio_rtp_ready.to_string();
|
||||||
audio_rtcp_ready.label = peer_info.audio_rtcp_ready.to_string();
|
audio_rtcp_ready.label = peer_info.audio_rtcp_ready.to_string();
|
||||||
audio_codec.label = peer_info.audio_codec + " " + peer_info.audio_clockrate.to_string();
|
audio_codec.label = peer_info.audio_codec + " " + peer_info.audio_clockrate.to_string();
|
||||||
|
audio_target_receive_bitrate.label = peer_info.audio_target_receive_bitrate.to_string();
|
||||||
|
audio_target_send_bitrate.label = peer_info.audio_target_send_bitrate.to_string();
|
||||||
|
|
||||||
video_rtp_ready.label = peer_info.video_rtp_ready.to_string();
|
video_rtp_ready.label = peer_info.video_rtp_ready.to_string();
|
||||||
video_rtcp_ready.label = peer_info.video_rtcp_ready.to_string();
|
video_rtcp_ready.label = peer_info.video_rtcp_ready.to_string();
|
||||||
video_codec.label = peer_info.video_codec;
|
video_codec.label = peer_info.video_codec;
|
||||||
|
video_target_receive_bitrate.label = peer_info.video_target_receive_bitrate.to_string();
|
||||||
|
video_target_send_bitrate.label = peer_info.video_target_send_bitrate.to_string();
|
||||||
|
|
||||||
if (peer_info.video_content_exists) add_video_widgets();
|
if (peer_info.video_content_exists) add_video_widgets();
|
||||||
|
|
||||||
if (prev_peer_info != null) {
|
if (prev_peer_info != null) {
|
||||||
audio_sent_bps.label = (peer_info.audio_bytes_sent - prev_peer_info.audio_bytes_sent).to_string();
|
ulong audio_sent_kbps = (peer_info.audio_bytes_sent - prev_peer_info.audio_bytes_sent) * 8 / 1000;
|
||||||
audio_recv_bps.label = (peer_info.audio_bytes_received - prev_peer_info.audio_bytes_received).to_string();
|
audio_sent_bps.label = "<span font_family='monospace'>%lu</span> kbps".printf(audio_sent_kbps);
|
||||||
video_sent_bps.label = (peer_info.video_bytes_sent - prev_peer_info.video_bytes_sent).to_string();
|
ulong audio_recv_kbps = (peer_info.audio_bytes_received - prev_peer_info.audio_bytes_received) * 8 / 1000;
|
||||||
video_recv_bps.label = (peer_info.video_bytes_received - prev_peer_info.video_bytes_received).to_string();
|
audio_recv_bps.label = "<span font_family='monospace'>%lu</span> kbps".printf(audio_recv_kbps);
|
||||||
|
ulong video_sent_kbps = (peer_info.video_bytes_sent - prev_peer_info.video_bytes_sent) * 8 / 1000;
|
||||||
|
video_sent_bps.label = "<span font_family='monospace'>%lu</span> kbps".printf(video_sent_kbps);
|
||||||
|
ulong video_recv_kbps = (peer_info.video_bytes_received - prev_peer_info.video_bytes_received) * 8 / 1000;
|
||||||
|
video_recv_bps.label = "<span font_family='monospace'>%lu</span> kbps".printf(video_recv_kbps);
|
||||||
}
|
}
|
||||||
prev_peer_info = peer_info;
|
prev_peer_info = peer_info;
|
||||||
}
|
}
|
||||||
|
@ -76,6 +92,10 @@ namespace Dino.Ui {
|
||||||
grid.attach(video_recv_bps, 1, row_at++, 1, 1);
|
grid.attach(video_recv_bps, 1, row_at++, 1, 1);
|
||||||
put_row("Codec");
|
put_row("Codec");
|
||||||
grid.attach(video_codec, 1, row_at++, 1, 1);
|
grid.attach(video_codec, 1, row_at++, 1, 1);
|
||||||
|
put_row("Target receive bitrate");
|
||||||
|
grid.attach(video_target_receive_bitrate, 1, row_at++, 1, 1);
|
||||||
|
put_row("Target send bitrate");
|
||||||
|
grid.attach(video_target_send_bitrate, 1, row_at++, 1, 1);
|
||||||
|
|
||||||
video_added = true;
|
video_added = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,7 +153,7 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream {
|
||||||
plugin.unpause();
|
plugin.unpause();
|
||||||
|
|
||||||
GLib.Signal.emit_by_name(rtpbin, "get-session", rtpid, out session);
|
GLib.Signal.emit_by_name(rtpbin, "get-session", rtpid, out session);
|
||||||
if (session != null && payload_type.rtcp_fbs.any_match((it) => it.type_ == "goog-remb")) {
|
if (session != null && remb_enabled) {
|
||||||
Object internal_session;
|
Object internal_session;
|
||||||
session.@get("internal-session", out internal_session);
|
session.@get("internal-session", out internal_session);
|
||||||
if (internal_session != null) {
|
if (internal_session != null) {
|
||||||
|
@ -166,7 +166,6 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint remb = 256;
|
|
||||||
private int last_packets_lost = -1;
|
private int last_packets_lost = -1;
|
||||||
private uint64 last_packets_received;
|
private uint64 last_packets_received;
|
||||||
private uint64 last_octets_received;
|
private uint64 last_octets_received;
|
||||||
|
@ -212,12 +211,12 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream {
|
||||||
if (new_received == 0) continue;
|
if (new_received == 0) continue;
|
||||||
double loss_rate = (double)new_lost / (double)(new_lost + new_received);
|
double loss_rate = (double)new_lost / (double)(new_lost + new_received);
|
||||||
if (new_lost <= 0 || loss_rate < 0.02) {
|
if (new_lost <= 0 || loss_rate < 0.02) {
|
||||||
remb = (uint)(1.08 * (double)remb);
|
target_receive_bitrate = (uint)(1.08 * (double)target_receive_bitrate);
|
||||||
} else if (loss_rate > 0.1) {
|
} else if (loss_rate > 0.1) {
|
||||||
remb = (uint)((1.0 - 0.5 * loss_rate) * (double)remb);
|
target_receive_bitrate = (uint)((1.0 - 0.5 * loss_rate) * (double)target_receive_bitrate);
|
||||||
}
|
}
|
||||||
remb = uint.max(remb, (uint)((new_octets * 8) / 1000));
|
target_receive_bitrate = uint.max(target_receive_bitrate, (uint)((new_octets * 8) / 1000));
|
||||||
remb = uint.max(16, remb); // Never go below 16
|
target_receive_bitrate = uint.max(16, target_receive_bitrate); // Never go below 16
|
||||||
uint8[] data = new uint8[] {
|
uint8[] data = new uint8[] {
|
||||||
143, 206, 0, 5,
|
143, 206, 0, 5,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
|
@ -231,7 +230,7 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream {
|
||||||
data[6] = (uint8)((our_ssrc >> 8) & 0xff);
|
data[6] = (uint8)((our_ssrc >> 8) & 0xff);
|
||||||
data[7] = (uint8)(our_ssrc & 0xff);
|
data[7] = (uint8)(our_ssrc & 0xff);
|
||||||
uint8 br_exp = 0;
|
uint8 br_exp = 0;
|
||||||
uint32 br_mant = remb * 1000;
|
uint32 br_mant = target_receive_bitrate * 1000;
|
||||||
uint8 bits = (uint8)Math.log2(br_mant);
|
uint8 bits = (uint8)Math.log2(br_mant);
|
||||||
if (bits > 16) {
|
if (bits > 16) {
|
||||||
br_exp = (uint8)bits - 16;
|
br_exp = (uint8)bits - 16;
|
||||||
|
@ -258,8 +257,8 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream {
|
||||||
if (data[0] != 'R' || data[1] != 'E' || data[2] != 'M' || data[3] != 'B') return;
|
if (data[0] != 'R' || data[1] != 'E' || data[2] != 'M' || data[3] != 'B') return;
|
||||||
uint8 br_exp = data[5] >> 2;
|
uint8 br_exp = data[5] >> 2;
|
||||||
uint32 br_mant = (((uint32)data[5] & 0x3) << 16) + ((uint32)data[6] << 8) + (uint32)data[7];
|
uint32 br_mant = (((uint32)data[5] & 0x3) << 16) + ((uint32)data[6] << 8) + (uint32)data[7];
|
||||||
uint bitrate = (br_mant << br_exp) / 1000;
|
self.target_send_bitrate = (br_mant << br_exp) / 1000;
|
||||||
self.input_device.update_bitrate(self.payload_type, bitrate);
|
self.input_device.update_bitrate(self.payload_type, self.target_send_bitrate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
public abstract class Xmpp.Xep.JingleRtp.Stream : Object {
|
public abstract class Xmpp.Xep.JingleRtp.Stream : Object {
|
||||||
|
|
||||||
public Jingle.Content content { get; protected set; }
|
public Jingle.Content content { get; protected set; }
|
||||||
|
|
||||||
public string name { get {
|
public string name { get {
|
||||||
|
@ -54,6 +53,13 @@ public abstract class Xmpp.Xep.JingleRtp.Stream : Object {
|
||||||
return false;
|
return false;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
// Receiver Estimated Maximum Bitrate
|
||||||
|
public bool remb_enabled { get {
|
||||||
|
return payload_type != null ? payload_type.rtcp_fbs.any_match((it) => it.type_ == "goog-remb") : false;
|
||||||
|
}}
|
||||||
|
public uint target_receive_bitrate { get; set; default=256; }
|
||||||
|
public uint target_send_bitrate { get; set; default=256; }
|
||||||
|
|
||||||
protected Stream(Jingle.Content content) {
|
protected Stream(Jingle.Content content) {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue