[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