[Spice-devel] [spice-html5] implement handing of MJPEG display streams
Aric Stewart
aric at codeweavers.com
Mon Aug 27 08:59:37 PDT 2012
Signed-off-by: Aric Stewart <aric at codeweavers.com>
---
display.js | 66 ++++++++++++++++++++++++++++++++++++++++++
enums.js | 2 +
spicemsg.js | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 160 insertions(+), 0 deletions(-)
diff --git a/display.js b/display.js
index 3efabb1..dd0a2e2 100644
--- a/display.js
+++ b/display.js
@@ -421,6 +421,72 @@ SpiceDisplayConn.prototype.process_channel_message = function(msg)
return true;
}
+ if (msg.type == SPICE_MSG_DISPLAY_STREAM_CREATE)
+ {
+ var m = new SpiceMsgDisplayStreamCreate(msg.data);
+ DEBUG > 1 && console.log(this.type + ": MsgStreamCreate id" + m.id);
+ if (!this.streams)
+ this.streams = new Array();
+ if (this.streams[m.id])
+ console.log("Stream already exists");
+ else
+ this.streams[m.id] = m;
+ if (m.codec_type != SPICE_VIDEO_CODEC_TYPE_MJPEG)
+ console.log("Unhandled stream codec: "+m.codec_type);
+ return true;
+ }
+
+ if (msg.type == SPICE_MSG_DISPLAY_STREAM_DATA)
+ {
+ var 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)
+ {
+ var tmpstr = "data:image/jpeg,";
+ var img = new Image;
+ var i;
+ for (i = 0; i < m.data.length; i++)
+ {
+ tmpstr += '%';
+ if (m.data[i] < 16)
+ tmpstr += '0';
+ tmpstr += m.data[i].toString(16);
+ }
+ var strm_base = new SpiceMsgDisplayBase();
+ strm_base.surface_id = this.streams[m.base.id].surface_id;
+ strm_base.box = this.streams[m.base.id].dest;
+ strm_base.clip = this.streams[m.base.id].clip;
+ img.o =
+ { base: strm_base,
+ tag: "mjpeg." + m.base.id,
+ descriptor: null,
+ sc : this,
+ };
+ img.onload = handle_draw_jpeg_onload;
+ img.src = tmpstr;
+ }
+ return true;
+ }
+
+ if (msg.type == SPICE_MSG_DISPLAY_STREAM_CLIP)
+ {
+ var m = new SpiceMsgDisplayStreamClip(msg.data);
+ DEBUG > 1 && console.log(this.type + ": MsgStreamClip id" + m.id);
+ this.streams[m.id].clip = m.clip;
+ return true;
+ }
+
+ if (msg.type == SPICE_MSG_DISPLAY_STREAM_DESTROY)
+ {
+ var m = new SpiceMsgDisplayStreamDestroy(msg.data);
+ DEBUG > 1 && console.log(this.type + ": MsgStreamDestroy id" + m.id);
+ this.streams[m.id] = undefined;
+ return true;
+ }
return false;
}
diff --git a/enums.js b/enums.js
index cbf9056..fa541a4 100644
--- a/enums.js
+++ b/enums.js
@@ -278,3 +278,5 @@ var SPICE_CURSOR_TYPE_ALPHA = 0,
SPICE_CURSOR_TYPE_COLOR16 = 4,
SPICE_CURSOR_TYPE_COLOR24 = 5,
SPICE_CURSOR_TYPE_COLOR32 = 6;
+
+var SPICE_VIDEO_CODEC_TYPE_MJPEG = 1;
diff --git a/spicemsg.js b/spicemsg.js
index 79c76bc..31e54a0 100644
--- a/spicemsg.js
+++ b/spicemsg.js
@@ -789,3 +789,95 @@ function SpiceMsgcKeyUp(e)
/* Use the same functions as for KeyDown */
SpiceMsgcKeyUp.prototype.to_buffer = SpiceMsgcKeyDown.prototype.to_buffer;
SpiceMsgcKeyUp.prototype.buffer_size = SpiceMsgcKeyDown.prototype.buffer_size;
+
+function SpiceMsgDisplayStreamCreate(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgDisplayStreamCreate.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.surface_id = dv.getUint32(at, true); at += 4;
+ this.id = dv.getUint32(at, true); at += 4;
+ this.flags = dv.getUint8(at, true); at += 1;
+ this.codec_type = dv.getUint8(at, true); at += 1;
+ /*stamp */ at += 8;
+ this.stream_width = dv.getUint32(at, true); at += 4;
+ this.stream_height = dv.getUint32(at, true); at += 4;
+ this.src_width = dv.getUint32(at, true); at += 4;
+ this.src_height = dv.getUint32(at, true); at += 4;
+
+ this.dest = new SpiceRect;
+ at = this.dest.from_dv(dv, at, a);
+ this.clip = new SpiceClip;
+ this.clip.from_dv(dv, at, a);
+ },
+}
+
+function SpiceStreamDataHeader(a, at)
+{
+}
+
+SpiceStreamDataHeader.prototype =
+{
+ from_dv : function(dv, at, mb)
+ {
+ this.id = dv.getUint32(at, true); at += 4;
+ this.multi_media_time = dv.getUint32(at, true); at += 4;
+ return at;
+ },
+}
+
+function SpiceMsgDisplayStreamData(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgDisplayStreamData.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.base = new SpiceStreamDataHeader;
+ at = this.base.from_dv(dv, at, a);
+ this.data_size = dv.getUint32(at, true); at += 4;
+ this.data = dv.u8.subarray(at, at + this.data_size);
+ },
+}
+
+function SpiceMsgDisplayStreamClip(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgDisplayStreamClip.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.id = dv.getUint32(at, true); at += 4;
+ this.clip = new SpiceClip;
+ this.clip.from_dv(dv, at, a);
+ },
+}
+
+function SpiceMsgDisplayStreamDestroy(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgDisplayStreamDestroy.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.id = dv.getUint32(at, true); at += 4;
+ },
+}
--
1.7.7.5 (Apple Git-26)
More information about the Spice-devel
mailing list