[Spice-devel] [PATCH spice-server 02/28] server/red_worker: streams: moving mjpeg_encoder from Stream to StreamAgent

Alon Levy alevy at redhat.com
Sun Apr 14 06:11:21 PDT 2013


On Tue, Feb 26, 2013 at 01:03:48PM -0500, Yonit Halperin wrote:
> The mjpeg_encoder should be client specific, and not shared between
> different clients**, for the following reasons:
> (1) Since we use abbreviated jpeg datastream for mjpeg, employing the same
>     mjpeg_encoder for different clients might cause errors when the
>     clients decode the jpeg data.
> (2) The next patch introduces bit rate control to the mjpeg_encoder.
>     This feature depends on the bandwidth available, which is client
>     specific.
> 
> ** at least till we change multi-clients not to re-encode the same
>    streams.

ACK

> ---
>  server/red_worker.c | 38 ++++++++++++++++++++++----------------
>  1 file changed, 22 insertions(+), 16 deletions(-)
> 
> diff --git a/server/red_worker.c b/server/red_worker.c
> index a4a369a..dd8169e 100644
> --- a/server/red_worker.c
> +++ b/server/red_worker.c
> @@ -427,7 +427,6 @@ struct Stream {
>      int width;
>      int height;
>      SpiceRect dest_area;
> -    MJpegEncoder *mjpeg_encoder;
>      int top_down;
>      Stream *next;
>      RingItem link;
> @@ -448,6 +447,7 @@ typedef struct StreamAgent {
>      PipeItem destroy_item;
>      Stream *stream;
>      uint64_t last_send_time;
> +    MJpegEncoder *mjpeg_encoder;
>  
>      int frames;
>      int drops;
> @@ -2484,9 +2484,6 @@ static void red_release_stream(RedWorker *worker, Stream *stream)
>  {
>      if (!--stream->refs) {
>          spice_assert(!ring_item_is_linked(&stream->link));
> -        if (stream->mjpeg_encoder) {
> -            mjpeg_encoder_destroy(stream->mjpeg_encoder);
> -        }
>          red_free_stream(worker, stream);
>          worker->stream_count--;
>      }
> @@ -2587,6 +2584,7 @@ static void red_stop_stream(RedWorker *worker, Stream *stream)
>      spice_debug("stream %d", get_stream_id(worker, stream));
>      WORKER_FOREACH_DCC(worker, item, dcc) {
>          StreamAgent *stream_agent;
> +
>          stream_agent = &dcc->stream_agents[get_stream_id(worker, stream)];
>          region_clear(&stream_agent->vis_region);
>          region_clear(&stream_agent->clip);
> @@ -2889,6 +2887,7 @@ static void red_display_create_stream(DisplayChannelClient *dcc, Stream *stream)
>      agent->drops = 0;
>      agent->fps = MAX_FPS;
>      reset_rate(dcc, agent);
> +    agent->mjpeg_encoder = mjpeg_encoder_new();
>      red_channel_client_pipe_add(&dcc->common.base, &agent->create_item);
>  }
>  
> @@ -2914,8 +2913,6 @@ static void red_create_stream(RedWorker *worker, Drawable *drawable)
>      stream_width = src_rect->right - src_rect->left;
>      stream_height = src_rect->bottom - src_rect->top;
>  
> -    stream->mjpeg_encoder = mjpeg_encoder_new();
> -
>      ring_add(&worker->streams, &stream->link);
>      stream->current = drawable;
>      stream->last_time = drawable->creation_time;
> @@ -2973,6 +2970,10 @@ static void red_display_destroy_streams(DisplayChannelClient *dcc)
>          StreamAgent *agent = &dcc->stream_agents[i];
>          region_destroy(&agent->vis_region);
>          region_destroy(&agent->clip);
> +        if (agent->mjpeg_encoder) {
> +            mjpeg_encoder_destroy(agent->mjpeg_encoder);
> +            agent->mjpeg_encoder = NULL;
> +        }
>      }
>  }
>  
> @@ -8277,7 +8278,7 @@ static inline void display_begin_send_message(RedChannelClient *rcc)
>      red_channel_client_begin_send_message(rcc);
>  }
>  
> -static inline uint8_t *red_get_image_line(RedWorker *worker, SpiceChunks *chunks, size_t *offset,
> +static inline uint8_t *red_get_image_line(SpiceChunks *chunks, size_t *offset,
>                                            int *chunk_nr, int stride)
>  {
>      uint8_t *ret;
> @@ -8303,13 +8304,14 @@ static inline uint8_t *red_get_image_line(RedWorker *worker, SpiceChunks *chunks
>      return ret;
>  }
>  
> -static int encode_frame (RedWorker *worker, const SpiceRect *src,
> -                         const SpiceBitmap *image, Stream *stream)
> +static int encode_frame(DisplayChannelClient *dcc, const SpiceRect *src,
> +                        const SpiceBitmap *image, Stream *stream)
>  {
>      SpiceChunks *chunks;
>      uint32_t image_stride;
>      size_t offset;
>      int i, chunk;
> +    StreamAgent *agent = &dcc->stream_agents[stream - dcc->common.worker->streams_buf];
>  
>      chunks = image->data;
>      offset = 0;
> @@ -8318,7 +8320,7 @@ static int encode_frame (RedWorker *worker, const SpiceRect *src,
>  
>      const int skip_lines = stream->top_down ? src->top : image->y - (src->bottom - 0);
>      for (i = 0; i < skip_lines; i++) {
> -        red_get_image_line(worker, chunks, &offset, &chunk, image_stride);
> +        red_get_image_line(chunks, &offset, &chunk, image_stride);
>      }
>  
>      const unsigned int stream_height = src->bottom - src->top;
> @@ -8326,14 +8328,14 @@ static int encode_frame (RedWorker *worker, const SpiceRect *src,
>  
>      for (i = 0; i < stream_height; i++) {
>          uint8_t *src_line =
> -            (uint8_t *)red_get_image_line(worker, chunks, &offset, &chunk, image_stride);
> +            (uint8_t *)red_get_image_line(chunks, &offset, &chunk, image_stride);
>  
>          if (!src_line) {
>              return FALSE;
>          }
>  
> -        src_line += src->left * mjpeg_encoder_get_bytes_per_pixel(stream->mjpeg_encoder);
> -        if (mjpeg_encoder_encode_scanline(stream->mjpeg_encoder, src_line, stream_width) == 0)
> +        src_line += src->left * mjpeg_encoder_get_bytes_per_pixel(agent->mjpeg_encoder);
> +        if (mjpeg_encoder_encode_scanline(agent->mjpeg_encoder, src_line, stream_width) == 0)
>              return FALSE;
>      }
>  
> @@ -8387,17 +8389,17 @@ static inline int red_marshall_stream_data(RedChannelClient *rcc,
>      }
>  
>      outbuf_size = dcc->send_data.stream_outbuf_size;
> -    if (!mjpeg_encoder_start_frame(stream->mjpeg_encoder, image->u.bitmap.format,
> +    if (!mjpeg_encoder_start_frame(agent->mjpeg_encoder, image->u.bitmap.format,
>                                     width, height,
>                                     &dcc->send_data.stream_outbuf,
>                                     &outbuf_size)) {
>          return FALSE;
>      }
> -    if (!encode_frame(worker, &drawable->red_drawable->u.copy.src_area,
> +    if (!encode_frame(dcc, &drawable->red_drawable->u.copy.src_area,
>                        &image->u.bitmap, stream)) {
>          return FALSE;
>      }
> -    n = mjpeg_encoder_end_frame(stream->mjpeg_encoder);
> +    n = mjpeg_encoder_end_frame(agent->mjpeg_encoder);
>      dcc->send_data.stream_outbuf_size = outbuf_size;
>  
>      if (!drawable->sized_stream) {
> @@ -8801,6 +8803,10 @@ static void red_display_marshall_stream_end(RedChannelClient *rcc,
>      red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DESTROY, NULL);
>      destroy.id = get_stream_id(dcc->common.worker, agent->stream);
>  
> +    if (agent->mjpeg_encoder) {
> +        mjpeg_encoder_destroy(agent->mjpeg_encoder);
> +        agent->mjpeg_encoder = NULL;
> +    }
>      spice_marshall_msg_display_stream_destroy(base_marshaller, &destroy);
>  }
>  
> -- 
> 1.8.1
> 
> _______________________________________________
> 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