[Spice-commits] gtk/channel-display.c gtk/channel-display-mjpeg.c gtk/channel-display-priv.h spice-common
Yonit Halperin
yhalperi at kemper.freedesktop.org
Thu May 3 04:14:54 PDT 2012
gtk/channel-display-mjpeg.c | 12 ++---
gtk/channel-display-priv.h | 3 +
gtk/channel-display.c | 99 +++++++++++++++++++++++++++++++++++++++-----
spice-common | 2
4 files changed, 98 insertions(+), 18 deletions(-)
New commits:
commit f84e039f25d49b0f5d3b2fcfe4df15a209ea6a44
Author: Yonit Halperin <yhalperi at redhat.com>
Date: Sun Apr 1 13:28:21 2012 +0300
display: video streaming: add support for frames of different sizes
rhbz #815426
When playing a youtube video on Windows guest, the driver sometimes sends
images which contain a video frame, but also other parts of the
screen (e.g., the you tube process bar). In order to prevent glitches, we send these
images as part of the stream, using SPICE_MSG_DISPLAY_STREAM_DATA_SIZED.
diff --git a/gtk/channel-display-mjpeg.c b/gtk/channel-display-mjpeg.c
index aed3adf..627aab4 100644
--- a/gtk/channel-display-mjpeg.c
+++ b/gtk/channel-display-mjpeg.c
@@ -24,10 +24,10 @@
static void mjpeg_src_init(struct jpeg_decompress_struct *cinfo)
{
display_stream *st = SPICE_CONTAINEROF(cinfo->src, display_stream, mjpeg_src);
- SpiceMsgDisplayStreamData *data = spice_msg_in_parsed(st->msg_data);
+ uint8_t *data;
- cinfo->src->next_input_byte = data->data;
- cinfo->src->bytes_in_buffer = data->data_size;
+ cinfo->src->bytes_in_buffer = stream_get_current_frame(st, &data);
+ cinfo->src->next_input_byte = data;
}
static boolean mjpeg_src_fill(struct jpeg_decompress_struct *cinfo)
@@ -64,13 +64,13 @@ void stream_mjpeg_init(display_stream *st)
G_GNUC_INTERNAL
void stream_mjpeg_data(display_stream *st)
{
- SpiceMsgDisplayStreamCreate *info = spice_msg_in_parsed(st->msg_create);
gboolean back_compat = st->channel->priv->peer_hdr.major_version == 1;
- int width = info->stream_width;
- int height = info->stream_height;
+ int width;
+ int height;
uint8_t *dest;
uint8_t *lines[4];
+ stream_get_dimensions(st, &width, &height);
dest = malloc(width * height * 4);
if (st->out_frame) {
diff --git a/gtk/channel-display-priv.h b/gtk/channel-display-priv.h
index 6fb624a..d327c28 100644
--- a/gtk/channel-display-priv.h
+++ b/gtk/channel-display-priv.h
@@ -73,6 +73,9 @@ typedef struct display_stream {
SpiceChannel *channel;
} display_stream;
+void stream_get_dimensions(display_stream *st, int *width, int *height);
+uint32_t stream_get_current_frame(display_stream *st, uint8_t **data);
+
/* channel-display-mjpeg.c */
void stream_mjpeg_init(display_stream *st);
void stream_mjpeg_data(display_stream *st);
diff --git a/gtk/channel-display.c b/gtk/channel-display.c
index d3109bc..578cb03 100644
--- a/gtk/channel-display.c
+++ b/gtk/channel-display.c
@@ -597,6 +597,7 @@ static void spice_display_channel_init(SpiceDisplayChannel *channel)
#if defined(WIN32)
c->dc = create_compatible_dc();
#endif
+ spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_DISPLAY_CAP_SIZED_STREAM);
}
/* ------------------------------------------------------------------ */
@@ -962,7 +963,7 @@ static void display_handle_stream_create(SpiceChannel *channel, SpiceMsgIn *in)
static gboolean display_stream_schedule(display_stream *st)
{
guint32 time, d;
- SpiceMsgDisplayStreamData *op;
+ SpiceStreamDataHeader *op;
SpiceMsgIn *in;
if (st->timeout)
@@ -989,6 +990,72 @@ static gboolean display_stream_schedule(display_stream *st)
return FALSE;
}
+static SpiceRect *stream_get_dest(display_stream *st)
+{
+ if (st->msg_data == NULL ||
+ spice_msg_in_type(st->msg_data) != SPICE_MSG_DISPLAY_STREAM_DATA_SIZED) {
+ SpiceMsgDisplayStreamCreate *info = spice_msg_in_parsed(st->msg_create);
+
+ return &info->dest;
+ } else {
+ SpiceMsgDisplayStreamDataSized *op = spice_msg_in_parsed(st->msg_data);
+
+ return &op->dest;
+ }
+
+}
+
+static uint32_t stream_get_flags(display_stream *st)
+{
+ SpiceMsgDisplayStreamCreate *info = spice_msg_in_parsed(st->msg_create);
+
+ return info->flags;
+}
+
+G_GNUC_INTERNAL
+uint32_t stream_get_current_frame(display_stream *st, uint8_t **data)
+{
+ if (st->msg_data == NULL) {
+ *data = NULL;
+ return 0;
+ }
+
+ if (spice_msg_in_type(st->msg_data) == SPICE_MSG_DISPLAY_STREAM_DATA) {
+ SpiceMsgDisplayStreamData *op = spice_msg_in_parsed(st->msg_data);
+
+ *data = op->data;
+ return op->data_size;
+ } else {
+ SpiceMsgDisplayStreamDataSized *op = spice_msg_in_parsed(st->msg_data);
+
+ g_return_val_if_fail(spice_msg_in_type(st->msg_data) ==
+ SPICE_MSG_DISPLAY_STREAM_DATA_SIZED, 0);
+ *data = op->data;
+ return op->data_size;
+ }
+
+}
+
+G_GNUC_INTERNAL
+void stream_get_dimensions(display_stream *st, int *width, int *height)
+{
+ g_return_if_fail(width != NULL);
+ g_return_if_fail(height != NULL);
+
+ if (st->msg_data == NULL ||
+ spice_msg_in_type(st->msg_data) != SPICE_MSG_DISPLAY_STREAM_DATA_SIZED) {
+ SpiceMsgDisplayStreamCreate *info = spice_msg_in_parsed(st->msg_create);
+
+ *width = info->stream_width;
+ *height = info->stream_height;
+ } else {
+ SpiceMsgDisplayStreamDataSized *op = spice_msg_in_parsed(st->msg_data);
+
+ *width = op->width;
+ *height = op->height;
+ }
+}
+
/* main context */
static gboolean display_stream_render(display_stream *st)
{
@@ -1008,14 +1075,19 @@ static gboolean display_stream_render(display_stream *st)
}
if (st->out_frame) {
- SpiceMsgDisplayStreamCreate *info = spice_msg_in_parsed(st->msg_create);
+ int width;
+ int height;
+ SpiceRect *dest;
uint8_t *data;
int stride;
+ stream_get_dimensions(st, &width, &height);
+ dest = stream_get_dest(st);
+
data = st->out_frame;
- stride = info->stream_width * sizeof(uint32_t);
- if (!(info->flags & SPICE_STREAM_FLAGS_TOP_DOWN)) {
- data += stride * (info->src_height - 1);
+ stride = width * sizeof(uint32_t);
+ if (!(stream_get_flags(st) & SPICE_STREAM_FLAGS_TOP_DOWN)) {
+ data += stride * (height - 1);
stride = -stride;
}
@@ -1024,15 +1096,15 @@ static gboolean display_stream_render(display_stream *st)
#ifdef WIN32
SPICE_DISPLAY_CHANNEL(st->channel)->priv->dc,
#endif
- &info->dest, data,
- info->src_width, info->src_height, stride,
+ dest, data,
+ width, height, stride,
st->have_region ? &st->region : NULL);
if (st->surface->primary)
g_signal_emit(st->channel, signals[SPICE_DISPLAY_INVALIDATE], 0,
- info->dest.left, info->dest.top,
- info->dest.right - info->dest.left,
- info->dest.bottom - info->dest.top);
+ dest->left, dest->top,
+ dest->right - dest->left,
+ dest->bottom - dest->top);
}
st->msg_data = NULL;
@@ -1053,12 +1125,16 @@ static gboolean display_stream_render(display_stream *st)
static void display_handle_stream_data(SpiceChannel *channel, SpiceMsgIn *in)
{
SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
- SpiceMsgDisplayStreamData *op = spice_msg_in_parsed(in);
+ SpiceStreamDataHeader *op = spice_msg_in_parsed(in);
display_stream *st = c->streams[op->id];
guint32 mmtime;
mmtime = spice_session_get_mm_time(spice_channel_get_session(channel));
+ if (spice_msg_in_type(in) == SPICE_MSG_DISPLAY_STREAM_DATA_SIZED) {
+ SPICE_DEBUG("stream %d contains sized data", op->id);
+ }
+
if (op->multi_media_time == 0) {
g_critical("Received frame with invalid 0 timestamp! perhaps wrong graphic driver?");
op->multi_media_time = mmtime + 100; /* workaround... */
@@ -1324,6 +1400,7 @@ static const spice_msg_handler display_handlers[] = {
[ SPICE_MSG_DISPLAY_STREAM_CLIP ] = display_handle_stream_clip,
[ SPICE_MSG_DISPLAY_STREAM_DESTROY ] = display_handle_stream_destroy,
[ SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL ] = display_handle_stream_destroy_all,
+ [ SPICE_MSG_DISPLAY_STREAM_DATA_SIZED ] = display_handle_stream_data,
[ SPICE_MSG_DISPLAY_DRAW_FILL ] = display_handle_draw_fill,
[ SPICE_MSG_DISPLAY_DRAW_OPAQUE ] = display_handle_draw_opaque,
diff --git a/spice-common b/spice-common
index e96dbb4..22fc0b0 160000
--- a/spice-common
+++ b/spice-common
@@ -1 +1 @@
-Subproject commit e96dbb4172ec7a47a5b15d3b9e921e12623fddaa
+Subproject commit 22fc0b0145876b90385c1c88923bcd72a6380812
More information about the Spice-commits
mailing list