[Spice-devel] [PATCH v3] streaming: Use the frame dimensions reported by the video decoder
Pavel Grunt
pgrunt at redhat.com
Mon Jun 6 07:07:29 UTC 2016
On Fri, 2016-06-03 at 15:02 +0200, Francois Gouget wrote:
> The dimensions sent by the remote end are redundant and should not be
> trusted.
>
> Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
Acked-by: Pavel Grunt <pgrunt at redhat.com>
Thanks,
Pavel
> ---
> src/channel-display-gst.c | 41 +++++++++++++++++++++++++++++++++--------
> src/channel-display-mjpeg.c | 11 ++++++-----
> src/channel-display-priv.h | 3 +--
> src/channel-display.c | 24 +-----------------------
> 4 files changed, 41 insertions(+), 38 deletions(-)
>
> diff --git a/src/channel-display-gst.c b/src/channel-display-gst.c
> index ca6b6e7..c752639 100644
> --- a/src/channel-display-gst.c
> +++ b/src/channel-display-gst.c
> @@ -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 {
> + goto error;
> + }
> +
> + 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;
> }
> - free_frame(frame);
>
> + 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;
> }
> diff --git a/src/channel-display-mjpeg.c b/src/channel-display-mjpeg.c
> index a2dae82..4976d53 100644
> --- a/src/channel-display-mjpeg.c
> +++ b/src/channel-display-mjpeg.c
> @@ -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;
> 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 54bc30e..22e64e2 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);
More information about the Spice-devel
mailing list