Add support for stream reports.
This helps video playback do a slightly better job of keeping up in the browser. It's not a dramatic effect, but enough to start making video playback almost tolerable.
This commit is contained in:
parent
84562db7e4
commit
b76c734d16
69
display.js
69
display.js
@ -477,31 +477,48 @@ SpiceDisplayConn.prototype.process_channel_message = function(msg)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (msg.type == SPICE_MSG_DISPLAY_STREAM_DATA)
|
||||
if (msg.type == SPICE_MSG_DISPLAY_STREAM_DATA ||
|
||||
msg.type == SPICE_MSG_DISPLAY_STREAM_DATA_SIZED)
|
||||
{
|
||||
var m = new SpiceMsgDisplayStreamData(msg.data);
|
||||
var m;
|
||||
if (msg.type == SPICE_MSG_DISPLAY_STREAM_DATA_SIZED)
|
||||
m = new SpiceMsgDisplayStreamDataSized(msg.data);
|
||||
else
|
||||
m = new SpiceMsgDisplayStreamData(msg.data);
|
||||
|
||||
if (!this.streams[m.base.id])
|
||||
{
|
||||
console.log("no stream for data");
|
||||
return false;
|
||||
}
|
||||
if (this.streams[m.base.id].codec_type === SPICE_VIDEO_CODEC_TYPE_MJPEG)
|
||||
{
|
||||
process_mjpeg_stream_data(this, m);
|
||||
|
||||
}
|
||||
var mmtime = (Date.now() - this.parent.our_mm_time) + this.parent.mm_time;
|
||||
var latency = m.base.multi_media_time - mmtime;
|
||||
|
||||
if (this.streams[m.base.id].codec_type === SPICE_VIDEO_CODEC_TYPE_MJPEG)
|
||||
process_mjpeg_stream_data(this, m, latency);
|
||||
|
||||
if ("report" in this.streams[m.base.id])
|
||||
process_stream_data_report(this, m, mmtime, latency);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (msg.type == SPICE_MSG_DISPLAY_STREAM_DATA_SIZED)
|
||||
if (msg.type == SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT)
|
||||
{
|
||||
var m = new SpiceMsgDisplayStreamDataSized(msg.data);
|
||||
if (this.streams[m.base.id].codec_type === SPICE_VIDEO_CODEC_TYPE_MJPEG)
|
||||
process_mjpeg_stream_data(this, m);
|
||||
var m = new SpiceMsgDisplayStreamActivateReport(msg.data);
|
||||
|
||||
var report = new SpiceMsgcDisplayStreamReport(m.stream_id, m.unique_id);
|
||||
if (this.streams[m.stream_id])
|
||||
{
|
||||
this.streams[m.stream_id].report = report;
|
||||
this.streams[m.stream_id].max_window_size = m.max_window_size;
|
||||
this.streams[m.stream_id].timeout_ms = m.timeout_ms
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (msg.type == SPICE_MSG_DISPLAY_STREAM_CLIP)
|
||||
{
|
||||
var m = new SpiceMsgDisplayStreamClip(msg.data);
|
||||
@ -811,8 +828,15 @@ function handle_draw_jpeg_onload()
|
||||
}
|
||||
}
|
||||
|
||||
function process_mjpeg_stream_data(sc, m)
|
||||
function process_mjpeg_stream_data(sc, m, latency)
|
||||
{
|
||||
if (latency < 0)
|
||||
{
|
||||
if ("report" in sc.streams[m.base.id])
|
||||
sc.streams[m.base.id].report.num_drops++;
|
||||
return;
|
||||
}
|
||||
|
||||
var tmpstr = "data:image/jpeg,";
|
||||
var img = new Image;
|
||||
var i;
|
||||
@ -837,3 +861,24 @@ function process_mjpeg_stream_data(sc, m)
|
||||
img.src = tmpstr;
|
||||
}
|
||||
|
||||
function process_stream_data_report(sc, m, mmtime, latency)
|
||||
{
|
||||
sc.streams[m.base.id].report.num_frames++;
|
||||
if (sc.streams[m.base.id].report.start_frame_mm_time == 0)
|
||||
sc.streams[m.base.id].report.start_frame_mm_time = m.base.multi_media_time;
|
||||
|
||||
if (sc.streams[m.base.id].report.num_frames > sc.streams[m.base.id].max_window_size ||
|
||||
(m.base.multi_media_time - sc.streams[m.base.id].report.start_frame_mm_time) > sc.streams[m.base.id].timeout_ms)
|
||||
{
|
||||
sc.streams[m.base.id].report.end_frame_mm_time = m.base.multi_media_time;
|
||||
sc.streams[m.base.id].report.last_frame_delay = latency;
|
||||
|
||||
var msg = new SpiceMiniData();
|
||||
msg.build_msg(SPICE_MSGC_DISPLAY_STREAM_REPORT, sc.streams[m.base.id].report);
|
||||
sc.send_msg(msg);
|
||||
|
||||
sc.streams[m.base.id].report.start_frame_mm_time = 0;
|
||||
sc.streams[m.base.id].report.num_frames = 0;
|
||||
sc.streams[m.base.id].report.num_drops = 0;
|
||||
}
|
||||
}
|
||||
|
1
enums.js
1
enums.js
@ -133,6 +133,7 @@ var SPICE_MSG_DISPLAY_DRAW_COMPOSITE = 318;
|
||||
var SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT = 319;
|
||||
|
||||
var SPICE_MSGC_DISPLAY_INIT = 101;
|
||||
var SPICE_MSGC_DISPLAY_STREAM_REPORT = 102;
|
||||
|
||||
var SPICE_MSG_INPUTS_INIT = 101;
|
||||
var SPICE_MSG_INPUTS_KEY_MODIFIERS = 102;
|
||||
|
3
main.js
3
main.js
@ -86,6 +86,9 @@ SpiceMainConn.prototype.process_channel_message = function(msg)
|
||||
" ; ram_hint " + this.main_init.ram_hint);
|
||||
}
|
||||
|
||||
this.our_mm_time = Date.now();
|
||||
this.mm_time = this.main_init.multi_media_time;
|
||||
|
||||
this.handle_mouse_mode(this.main_init.current_mouse_mode,
|
||||
this.main_init.supported_mouse_modes);
|
||||
|
||||
|
@ -135,7 +135,8 @@ SpiceConn.prototype =
|
||||
);
|
||||
else if (msg.channel_type == SPICE_CHANNEL_DISPLAY)
|
||||
msg.channel_caps.push(
|
||||
(1 << SPICE_DISPLAY_CAP_SIZED_STREAM)
|
||||
(1 << SPICE_DISPLAY_CAP_SIZED_STREAM) |
|
||||
(1 << SPICE_DISPLAY_CAP_STREAM_REPORT)
|
||||
);
|
||||
|
||||
hdr.size = msg.buffer_size();
|
||||
|
54
spicemsg.js
54
spicemsg.js
@ -1201,6 +1201,60 @@ SpiceMsgDisplayStreamDestroy.prototype =
|
||||
},
|
||||
}
|
||||
|
||||
function SpiceMsgDisplayStreamActivateReport(a, at)
|
||||
{
|
||||
this.from_buffer(a, at);
|
||||
}
|
||||
|
||||
SpiceMsgDisplayStreamActivateReport.prototype =
|
||||
{
|
||||
from_buffer: function(a, at)
|
||||
{
|
||||
at = at || 0;
|
||||
var dv = new SpiceDataView(a);
|
||||
this.stream_id = dv.getUint32(at, true); at += 4;
|
||||
this.unique_id = dv.getUint32(at, true); at += 4;
|
||||
this.max_window_size = dv.getUint32(at, true); at += 4;
|
||||
this.timeout_ms = dv.getUint32(at, true); at += 4;
|
||||
},
|
||||
}
|
||||
|
||||
function SpiceMsgcDisplayStreamReport(stream_id, unique_id)
|
||||
{
|
||||
this.stream_id = stream_id;
|
||||
this.unique_id = unique_id;
|
||||
this.start_frame_mm_time = 0;
|
||||
this.end_frame_mm_time = 0;
|
||||
this.num_frames = 0;
|
||||
this.num_drops = 0;
|
||||
this.last_frame_delay = 0;
|
||||
|
||||
// TODO - Implement audio delay
|
||||
this.audio_delay = -1;
|
||||
}
|
||||
|
||||
SpiceMsgcDisplayStreamReport.prototype =
|
||||
{
|
||||
to_buffer: function(a, at)
|
||||
{
|
||||
at = at || 0;
|
||||
var dv = new SpiceDataView(a);
|
||||
dv.setUint32(at, this.stream_id, true); at += 4;
|
||||
dv.setUint32(at, this.unique_id, true); at += 4;
|
||||
dv.setUint32(at, this.start_frame_mm_time, true); at += 4;
|
||||
dv.setUint32(at, this.end_frame_mm_time, true); at += 4;
|
||||
dv.setUint32(at, this.num_frames, true); at += 4;
|
||||
dv.setUint32(at, this.num_drops, true); at += 4;
|
||||
dv.setUint32(at, this.last_frame_delay, true); at += 4;
|
||||
dv.setUint32(at, this.audio_delay, true); at += 4;
|
||||
return at;
|
||||
},
|
||||
buffer_size: function()
|
||||
{
|
||||
return 8 * 4;
|
||||
}
|
||||
}
|
||||
|
||||
function SpiceMsgDisplayInvalList(a, at)
|
||||
{
|
||||
this.count = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user