[Spice-devel] [PATCH] mjpeg: fix libjpeg assertion

Alon Levy alevy at redhat.com
Fri Jul 29 15:16:16 PDT 2011


On Fri, Jul 29, 2011 at 05:28:35PM +0200, Christophe Fergeau wrote:

ACK.

> After the changes to add libjpeg-turbo support to spice-server mjpeg
> compression code, it's relatively easy to hit an assertion from
> libjpeg in spice-server about "too few scanlines transferred" when
> the mjpeg streaming code triggers. This assertion brings down qemu,
> which is bad :)
> 
> This is because when we first initialize the mjpeg encoder, we do:
> 
> stream_width = SPICE_ALIGN(src_rect->right - src_rect->left, 2);
> stream_height = SPICE_ALIGN(src_rect->bottom - src_rect->top, 2);
> 
> stream->mjpeg_encoder = mjpeg_encoder_new(stream_width, stream_height);
> 
> and then when we iterate over the image scanlines to feed them to
> libjpeg, we do:
> 
> const int image_height = src->bottom - src->top;
> const int image_width = src->right - src->left;
> 
> for (i = 0; i < image_height; i++) {
>     mjpeg_encoder_encode_scanline(...);
> }
> mjpeg_encoder_end_frame(...);
> 
> When stream_height is odd, the mjpeg_encoder will be created with
> an height that is 1 more than the number of lines we encode. Then
> libjpeg asserts when we tell it we're done with the compression
> while it's still waiting for one more scanline.
> 
> Looking through git history, this rounding seems to be an artifact
> from when we were using ffmpeg for the mjpeg encoding. Since
> spicec and spicy (the latter needs a few fixes) can handle streams
> with odd height/width, the best way to solve this issue is to stop
> rounding up the height and width of the streams we create. This
> even saves some bandwidth :)
> ---
>  server/red_worker.c |   16 ++++++++--------
>  1 files changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/server/red_worker.c b/server/red_worker.c
> index 6737940..efedc19 100644
> --- a/server/red_worker.c
> +++ b/server/red_worker.c
> @@ -2417,8 +2417,8 @@ static void red_create_stream(RedWorker *worker, Drawable *drawable)
>  
>      ASSERT(drawable->red_drawable->type == QXL_DRAW_COPY);
>      src_rect = &drawable->red_drawable->u.copy.src_area;
> -    stream_width = SPICE_ALIGN(src_rect->right - src_rect->left, 2);
> -    stream_height = SPICE_ALIGN(src_rect->bottom - src_rect->top, 2);
> +    stream_width = src_rect->right - src_rect->left;
> +    stream_height = src_rect->bottom - src_rect->top;
>  
>      stream->mjpeg_encoder = mjpeg_encoder_new(stream_width, stream_height);
>  
> @@ -7329,10 +7329,10 @@ static int encode_frame (RedWorker *worker, const SpiceRect *src,
>          red_get_image_line(worker, chunks, &offset, &chunk, image_stride);
>      }
>  
> -    const int image_height = src->bottom - src->top;
> -    const int image_width = src->right - src->left;
> +    const unsigned int stream_height = src->bottom - src->top;
> +    const unsigned int stream_width = src->right - src->left;
>  
> -    for (i = 0; i < image_height; i++) {
> +    for (i = 0; i < stream_height; i++) {
>          uint8_t *src_line =
>              (uint8_t *)red_get_image_line(worker, chunks, &offset, &chunk, image_stride);
>  
> @@ -7341,7 +7341,7 @@ static int encode_frame (RedWorker *worker, const SpiceRect *src,
>          }
>  
>          src_line += src->left * mjpeg_encoder_get_bytes_per_pixel(stream->mjpeg_encoder);
> -        if (mjpeg_encoder_encode_scanline(stream->mjpeg_encoder, src_line, image_width) == 0)
> +        if (mjpeg_encoder_encode_scanline(stream->mjpeg_encoder, src_line, stream_width) == 0)
>              return FALSE;
>      }
>  
> @@ -7705,8 +7705,8 @@ static void red_display_marshall_stream_start(DisplayChannel *display_channel,
>  
>      stream_create.src_width = stream->width;
>      stream_create.src_height = stream->height;
> -    stream_create.stream_width = SPICE_ALIGN(stream_create.src_width, 2);
> -    stream_create.stream_height = SPICE_ALIGN(stream_create.src_height, 2);
> +    stream_create.stream_width = stream_create.src_width;
> +    stream_create.stream_height = stream_create.src_height;
>      stream_create.dest = stream->dest_area;
>  
>      if (stream->current) {
> -- 
> 1.7.6
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel


More information about the Spice-devel mailing list