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