[Spice-devel] [RFC PATCH 10/16] stream-device: Handle streaming data from device to channel
Frediano Ziglio
fziglio at redhat.com
Wed Jan 25 12:42:33 UTC 2017
Handle stream data from device sending to the channel.
Channel will forward to clients as proper DisplayChannel
messaging creating and destroying the channel stream as
needed.
Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
---
server/stream-channel.c | 105 +++++++++++++++++++++++++++++++++++++++++-
server/stream-channel.h | 6 ++-
server/stream-device.c | 4 +-
3 files changed, 113 insertions(+), 2 deletions(-)
diff --git a/server/stream-channel.c b/server/stream-channel.c
index 79beb4d..be119f8 100644
--- a/server/stream-channel.c
+++ b/server/stream-channel.c
@@ -20,6 +20,7 @@
#endif
#include <common/generated_server_marshallers.h>
+#include <spice/stream-device.h>
#include "red-channel-client.h"
#include "stream-channel.h"
@@ -44,6 +45,8 @@ typedef struct StreamChannelClientClass StreamChannelClientClass;
struct StreamChannelClient {
RedChannelClient parent;
+
+ int stream_id;
};
struct StreamChannelClientClass {
@@ -56,6 +59,8 @@ G_DEFINE_TYPE(StreamChannelClient, stream_channel_client, RED_TYPE_CHANNEL_CLIEN
struct StreamChannel {
CommonGraphicsChannel parent;
+
+ int stream_id;
};
struct StreamChannelClass {
@@ -67,8 +72,22 @@ G_DEFINE_TYPE(StreamChannel, stream_channel, TYPE_COMMON_GRAPHICS_CHANNEL)
enum {
RED_PIPE_ITEM_TYPE_SURFACE_CREATE = RED_PIPE_ITEM_TYPE_COMMON_LAST,
RED_PIPE_ITEM_TYPE_FILL_SURFACE,
+ RED_PIPE_ITEM_TYPE_STREAM_CREATE,
+ RED_PIPE_ITEM_TYPE_STREAM_DATA,
+ RED_PIPE_ITEM_TYPE_STREAM_DESTROY,
};
+typedef struct StreamCreateItem {
+ RedPipeItem base;
+ SpiceMsgDisplayStreamCreate stream_create;
+} StreamCreateItem;
+
+typedef struct StreamDataItem {
+ RedPipeItem base;
+ // NOTE: this must be the last field in the structure
+ SpiceMsgDisplayStreamData data;
+} StreamDataItem;
+
static void
stream_channel_client_class_init(StreamChannelClientClass *klass)
{
@@ -77,6 +96,7 @@ stream_channel_client_class_init(StreamChannelClientClass *klass)
static void
stream_channel_client_init(StreamChannelClient *client)
{
+ client->stream_id = -1;
}
static void
@@ -139,6 +159,7 @@ static void
stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
{
SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
+ StreamChannelClient *client = STREAM_CHANNEL_CLIENT(rcc);
switch (pipe_item->type) {
case RED_PIPE_ITEM_TYPE_SURFACE_CREATE: {
@@ -160,6 +181,32 @@ stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
spice_marshall_Fill(m, &fill, &brush_pat_out, &mask_bitmap_out);
break;
}
+ case RED_PIPE_ITEM_TYPE_STREAM_CREATE: {
+ StreamCreateItem *item = SPICE_UPCAST(StreamCreateItem, pipe_item);
+ client->stream_id = item->stream_create.id;
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_CREATE);
+ spice_marshall_msg_display_stream_create(m, &item->stream_create);
+ break;
+ }
+ case RED_PIPE_ITEM_TYPE_STREAM_DATA: {
+ StreamDataItem *item = SPICE_UPCAST(StreamDataItem, pipe_item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DATA);
+ spice_marshall_msg_display_stream_data(m, &item->data);
+ red_pipe_item_ref(pipe_item);
+ spice_marshaller_add_by_ref_full(m, item->data.data, item->data.data_size,
+ marshaller_unref_pipe_item, pipe_item);
+ break;
+ }
+ case RED_PIPE_ITEM_TYPE_STREAM_DESTROY: {
+ if (client->stream_id < 0) {
+ return;
+ }
+ SpiceMsgDisplayStreamDestroy stream_destroy = { client->stream_id };
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DESTROY);
+ spice_marshall_msg_display_stream_destroy(m, &stream_destroy);
+ client->stream_id = -1;
+ break;
+ }
default:
spice_error("invalid pipe item type");
}
@@ -273,4 +320,62 @@ stream_channel_class_init(StreamChannelClass *klass)
static void
stream_channel_init(StreamChannel *channel)
{
+ channel->stream_id = -1;
+}
+
+static RedPipeItem *
+pipe_item_new_ref(G_GNUC_UNUSED RedChannelClient *rcc, void *data, G_GNUC_UNUSED int num)
+{
+ RedPipeItem *item = data;
+ red_pipe_item_ref(item);
+ return item;
+}
+
+void
+stream_channel_change_format(StreamChannel *channel, const struct StreamMsgStreamFormat *fmt)
+{
+ RedChannel *red_channel = RED_CHANNEL(channel);
+
+ // send destroy old stream
+ red_channel_pipes_add_type(red_channel, RED_PIPE_ITEM_TYPE_STREAM_DESTROY);
+
+ // TODO send new create surface if required
+
+ // allocate a new stream id
+ channel->stream_id = (channel->stream_id + 1) % 40;
+
+ // send create stream
+ StreamCreateItem *item = spice_new0(StreamCreateItem, 1);
+ red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_STREAM_CREATE);
+ item->stream_create.id = channel->stream_id;
+ item->stream_create.flags = SPICE_STREAM_FLAGS_TOP_DOWN;
+ item->stream_create.codec_type = fmt->codec;
+ item->stream_create.stream_width = fmt->width;
+ item->stream_create.stream_height = fmt->height;
+ item->stream_create.src_width = fmt->width;
+ item->stream_create.src_height = fmt->height;
+ item->stream_create.dest = (SpiceRect) { 0, 0, fmt->width, fmt->height };
+ item->stream_create.clip = (SpiceClip) { SPICE_CLIP_TYPE_NONE, NULL };
+ red_channel_pipes_new_add(red_channel, pipe_item_new_ref, item);
+ red_pipe_item_unref(&item->base);
+}
+
+void
+stream_channel_send_data(StreamChannel *channel, const void *data, size_t size)
+{
+ if (channel->stream_id < 0) {
+ return;
+ }
+
+ RedChannel *red_channel = RED_CHANNEL(channel);
+
+ StreamDataItem *item = spice_malloc(sizeof(*item) + size);
+ red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_STREAM_DATA);
+ item->data.base.id = channel->stream_id;
+ item->data.base.multi_media_time = reds_get_mm_time();
+ item->data.data_size = size;
+ // TODO try to optimize avoiding the copy
+ memcpy(item->data.data, data, size);
+ red_channel_pipes_new_add(red_channel, pipe_item_new_ref, item);
+ red_pipe_item_unref(&item->base);
}
diff --git a/server/stream-channel.h b/server/stream-channel.h
index 7390383..bb66ac6 100644
--- a/server/stream-channel.h
+++ b/server/stream-channel.h
@@ -47,6 +47,12 @@ GType stream_channel_get_type(void) G_GNUC_CONST;
*/
StreamChannel* stream_channel_new(RedsState *server);
+struct StreamMsgStreamFormat;
+
+void stream_channel_change_format(StreamChannel *channel,
+ const struct StreamMsgStreamFormat *fmt);
+void stream_channel_send_data(StreamChannel *channel, const void *data, size_t size);
+
G_END_DECLS
#endif /* STREAM_CHANNEL_H_ */
diff --git a/server/stream-device.c b/server/stream-device.c
index 35ba3f0..da71880 100644
--- a/server/stream-device.c
+++ b/server/stream-device.c
@@ -122,6 +122,7 @@ handle_msg_format(StreamDevice *dev, SpiceCharDeviceInstance *sin)
spice_assert(n == sizeof(fmt));
fmt.width = GUINT32_FROM_LE(fmt.width);
fmt.height = GUINT32_FROM_LE(fmt.height);
+ stream_channel_change_format(dev->channel, &fmt);
dev->hdr_pos = 0;
}
@@ -133,11 +134,10 @@ handle_msg_data(StreamDevice *dev, SpiceCharDeviceInstance *sin)
do {
uint8_t buf[16 * 1024];
n = sif->read(sin, buf, sizeof(buf));
- /* FIXME */
- printf("readed %d bytes from device\n", n);
if (n <= 0) {
break;
}
+ stream_channel_send_data(dev->channel, buf, n);
dev->hdr.size -= n;
} while (n > 0);
if (dev->hdr.size == 0) {
--
git-series 0.9.1
More information about the Spice-devel
mailing list