mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice-gtk
synced 2026-02-03 20:30:35 +00:00
streaming: Use the frame dimensions reported by the video decoder
The dimensions sent by the remote end are redundant and should not be trusted. Signed-off-by: Francois Gouget <fgouget@codeweavers.com> Acked-by: Pavel Grunt <pgrunt@redhat.com>
This commit is contained in:
parent
3666ec4d5c
commit
b2e6f64da9
@ -87,26 +87,51 @@ static void schedule_frame(SpiceGstDecoder *decoder);
|
||||
static gboolean display_frame(gpointer video_decoder)
|
||||
{
|
||||
SpiceGstDecoder *decoder = (SpiceGstDecoder*)video_decoder;
|
||||
SpiceFrame *frame;
|
||||
GstCaps *caps;
|
||||
gint width, height;
|
||||
GstStructure *s;
|
||||
GstBuffer *buffer;
|
||||
GstMapInfo mapinfo;
|
||||
|
||||
decoder->timer_id = 0;
|
||||
|
||||
g_mutex_lock(&decoder->queues_mutex);
|
||||
SpiceFrame *frame = g_queue_pop_head(decoder->display_queue);
|
||||
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);
|
||||
gst_buffer_unmap(buffer, &mapinfo);
|
||||
} else {
|
||||
spice_warning("GStreamer error: could not map the buffer");
|
||||
goto error;
|
||||
}
|
||||
free_frame(frame);
|
||||
|
||||
caps = gst_sample_get_caps(frame->sample);
|
||||
if (!caps) {
|
||||
spice_warning("GStreamer error: could not get the caps of the sample");
|
||||
goto error;
|
||||
}
|
||||
|
||||
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");
|
||||
goto error;
|
||||
}
|
||||
|
||||
buffer = gst_sample_get_buffer(frame->sample);
|
||||
if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) {
|
||||
spice_warning("GStreamer error: could not map the buffer");
|
||||
goto error;
|
||||
}
|
||||
|
||||
stream_display_frame(decoder->base.stream, frame->msg,
|
||||
width, height, mapinfo.data);
|
||||
gst_buffer_unmap(buffer, &mapinfo);
|
||||
|
||||
error:
|
||||
free_frame(frame);
|
||||
schedule_frame(decoder);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
@ -86,12 +86,13 @@ 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;
|
||||
JDIMENSION width, height;
|
||||
uint8_t *dest;
|
||||
uint8_t *lines[4];
|
||||
|
||||
stream_get_dimensions(decoder->base.stream, decoder->cur_frame_msg, &width, &height);
|
||||
jpeg_read_header(&decoder->mjpeg_cinfo, 1);
|
||||
width = decoder->mjpeg_cinfo.image_width;
|
||||
height = decoder->mjpeg_cinfo.image_height;
|
||||
if (decoder->out_size < width * height * 4) {
|
||||
g_free(decoder->out_frame);
|
||||
decoder->out_size = width * height * 4;
|
||||
@ -99,7 +100,6 @@ static gboolean mjpeg_decoder_decode_frame(gpointer video_decoder)
|
||||
}
|
||||
dest = decoder->out_frame;
|
||||
|
||||
jpeg_read_header(&decoder->mjpeg_cinfo, 1);
|
||||
#ifdef JCS_EXTENSIONS
|
||||
// requires jpeg-turbo
|
||||
if (back_compat)
|
||||
@ -168,7 +168,8 @@ static gboolean mjpeg_decoder_decode_frame(gpointer video_decoder)
|
||||
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,
|
||||
width, height, decoder->out_frame);
|
||||
spice_msg_in_unref(decoder->cur_frame_msg);
|
||||
decoder->cur_frame_msg = NULL;
|
||||
decoder->timer_id = 0;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
|
||||
@ -1173,26 +1173,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)
|
||||
{
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user