The dimensions sent by the remote end are redundant and should not be trusted. Signed-off-by: Francois Gouget <fgouget@xxxxxxxxxxxxxxx> --- src/channel-display-gst.c | 40 +++++++++++++++++++++++++++++++--------- src/channel-display-mjpeg.c | 25 +++++++++++++------------ src/channel-display-priv.h | 3 +-- src/channel-display.c | 24 +----------------------- 4 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/channel-display-gst.c b/src/channel-display-gst.c index 46a85ea..f8a460f 100644 --- a/src/channel-display-gst.c +++ b/src/channel-display-gst.c @@ -93,18 +93,40 @@ static gboolean display_frame(gpointer video_decoder) g_mutex_lock(&decoder->queues_mutex); SpiceFrame *frame = g_queue_pop_head(decoder->display_queue); g_mutex_unlock(&decoder->queues_mutex); + /* If the queue is empty we don't even need to reschedule */ g_return_val_if_fail(frame, G_SOURCE_REMOVE); - GstBuffer *buffer = frame->sample ? gst_sample_get_buffer(frame->sample) : NULL; - GstMapInfo mapinfo; - if (!frame->sample) { - spice_warning("got a frame without a sample!"); - } else if (gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) { - stream_display_frame(decoder->base.stream, frame->msg, mapinfo.data); + do { + if (!frame->sample) { + spice_warning("got a frame without a sample!"); + break; + } + + GstCaps *caps = gst_sample_get_caps(frame->sample); + if (!caps) { + spice_warning("GStreamer error: could not get the caps of the sample"); + break; + } + + gint width, height; + GstStructure *s = gst_caps_get_structure(caps, 0); + if (!gst_structure_get_int(s, "width", &width) || + !gst_structure_get_int(s, "height", &height)) { + spice_warning("GStreamer error: could not get the size of the frame"); + break; + } + + GstBuffer *buffer = gst_sample_get_buffer(frame->sample); + GstMapInfo mapinfo; + if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) { + spice_warning("GStreamer error: could not map the buffer"); + break; + } + + stream_display_frame(decoder->base.stream, frame->msg, + width, height, mapinfo.data); gst_buffer_unmap(buffer, &mapinfo); - } else { - spice_warning("GStreamer error: could not map the buffer"); - } + } while (FALSE); free_frame(frame); schedule_frame(decoder); diff --git a/src/channel-display-mjpeg.c b/src/channel-display-mjpeg.c index 1238b41..3327a6b 100644 --- a/src/channel-display-mjpeg.c +++ b/src/channel-display-mjpeg.c @@ -86,20 +86,18 @@ static gboolean mjpeg_decoder_decode_frame(gpointer video_decoder) { MJpegDecoder *decoder = (MJpegDecoder*)video_decoder; gboolean back_compat = decoder->base.stream->channel->priv->peer_hdr.major_version == 1; - int width; - int height; uint8_t *dest; uint8_t *lines[4]; - stream_get_dimensions(decoder->base.stream, decoder->cur_frame_msg, &width, &height); - if (decoder->out_size < width * height * 4) { + jpeg_read_header(&decoder->mjpeg_cinfo, 1); + uint32_t img_size = decoder->mjpeg_cinfo.image_width * decoder->mjpeg_cinfo.image_height * 4; + if (decoder->out_size < img_size) { g_free(decoder->out_frame); - decoder->out_size = width * height * 4; + decoder->out_size = img_size; decoder->out_frame = g_malloc(decoder->out_size); } dest = decoder->out_frame; - jpeg_read_header(&decoder->mjpeg_cinfo, 1); #ifdef JCS_EXTENSIONS // requires jpeg-turbo if (back_compat) @@ -134,9 +132,9 @@ static gboolean mjpeg_decoder_decode_frame(gpointer video_decoder) for (unsigned int j = 0; j < decoder->mjpeg_cinfo.rec_outbuf_height; j++) { lines[j] = dest; #ifdef JCS_EXTENSIONS - dest += 4 * width; + dest += 4 * decoder->mjpeg_cinfo.image_width; #else - dest += 3 * width; + dest += 3 * decoder->mjpeg_cinfo.image_width; #endif } lines_read = jpeg_read_scanlines(&decoder->mjpeg_cinfo, lines, @@ -147,14 +145,14 @@ static gboolean mjpeg_decoder_decode_frame(gpointer video_decoder) uint32_t *d = (uint32_t *)s; if (back_compat) { - for (unsigned int j = lines_read * width; j > 0; ) { + for (unsigned int j = lines_read * decoder->mjpeg_cinfo.image_width; j > 0; ) { j -= 1; // reverse order, bad for cache? d[j] = s[j * 3 + 0] | s[j * 3 + 1] << 8 | s[j * 3 + 2] << 16; } } else { - for (unsigned int j = lines_read * width; j > 0; ) { + for (unsigned int j = lines_read * decoder->mjpeg_cinfo.image_width; j > 0; ) { j -= 1; // reverse order, bad for cache? d[j] = s[j * 3 + 0] << 16 | s[j * 3 + 1] << 8 | @@ -163,12 +161,15 @@ static gboolean mjpeg_decoder_decode_frame(gpointer video_decoder) } } #endif - dest = &(decoder->out_frame[decoder->mjpeg_cinfo.output_scanline * width * 4]); + dest = &(decoder->out_frame[decoder->mjpeg_cinfo.output_scanline * decoder->mjpeg_cinfo.image_width * 4]); } jpeg_finish_decompress(&decoder->mjpeg_cinfo); /* Display the frame and dispose of it */ - stream_display_frame(decoder->base.stream, decoder->cur_frame_msg, decoder->out_frame); + stream_display_frame(decoder->base.stream, decoder->cur_frame_msg, + decoder->mjpeg_cinfo.image_width, + decoder->mjpeg_cinfo.image_height, + decoder->out_frame); spice_msg_in_unref(decoder->cur_frame_msg); decoder->cur_frame_msg = NULL; decoder->timer_id = 0; diff --git a/src/channel-display-priv.h b/src/channel-display-priv.h index 3155015..3fcf2e2 100644 --- a/src/channel-display-priv.h +++ b/src/channel-display-priv.h @@ -135,10 +135,9 @@ struct display_stream { uint32_t report_drops_seq_len; }; -void stream_get_dimensions(display_stream *st, SpiceMsgIn *frame_msg, int *width, int *height); guint32 stream_get_time(display_stream *st); void stream_dropped_frame_on_playback(display_stream *st); -void stream_display_frame(display_stream *st, SpiceMsgIn *frame_msg, uint8_t* data); +void stream_display_frame(display_stream *st, SpiceMsgIn *frame_msg, uint32_t width, uint32_t height, uint8_t *data); uint32_t spice_msg_in_frame_data(SpiceMsgIn *frame_msg, uint8_t **data); diff --git a/src/channel-display.c b/src/channel-display.c index 2b8ab4e..31ba574 100644 --- a/src/channel-display.c +++ b/src/channel-display.c @@ -1174,26 +1174,6 @@ uint32_t spice_msg_in_frame_data(SpiceMsgIn *frame_msg, uint8_t **data) } G_GNUC_INTERNAL -void stream_get_dimensions(display_stream *st, SpiceMsgIn *frame_msg, int *width, int *height) -{ - g_return_if_fail(width != NULL); - g_return_if_fail(height != NULL); - - if (frame_msg == NULL || - spice_msg_in_type(frame_msg) != 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(frame_msg); - - *width = op->width; - *height = op->height; - } -} - -G_GNUC_INTERNAL guint32 stream_get_time(display_stream *st) { SpiceSession *session = spice_channel_get_session(st->channel); @@ -1210,13 +1190,11 @@ void stream_dropped_frame_on_playback(display_stream *st) /* main context */ G_GNUC_INTERNAL void stream_display_frame(display_stream *st, SpiceMsgIn *frame_msg, - uint8_t* data) + uint32_t width, uint32_t height, uint8_t *data) { - int width, height; const SpiceRect *dest; int stride; - stream_get_dimensions(st, frame_msg, &width, &height); dest = stream_get_dest(st, frame_msg); stride = width * sizeof(uint32_t); -- 2.8.1 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel