[Spice-devel] [PATCH 10/11] Move stream functions to stream.[ch]

Jonathon Jongsma jjongsma at redhat.com
Tue Nov 17 08:19:49 PST 2015


On Tue, 2015-11-17 at 08:59 -0500, Frediano Ziglio wrote:
> > 
> > On Mon, 2015-11-16 at 15:02 +0100, Fabiano FidĂȘncio wrote:
> > > On Mon, Nov 16, 2015 at 12:06 PM, Frediano Ziglio <fziglio at redhat.com>
> > > wrote:
> > > > From: Jonathon Jongsma <jjongsma at redhat.com>
> > > > 
> > > > ---
> > > >  server/display-channel.h |   5 +
> > > >  server/red_worker.c      | 376
> > > >  +-------------------------------------------
> > > > ---
> > > >  server/stream.c          | 359
> > > >  ++++++++++++++++++++++++++++++++++++++++++++
> > > >  server/stream.h          |   9 ++
> > > >  4 files changed, 378 insertions(+), 371 deletions(-)
> > > > 
> > > > diff --git a/server/display-channel.h b/server/display-channel.h
> > > > index ae8a900..26b4e4e 100644
> > > > --- a/server/display-channel.h
> > > > +++ b/server/display-channel.h
> > > > @@ -166,6 +166,11 @@ struct Drawable {
> > > >      uint32_t process_commands_generation;
> > > >  };
> > > > 
> > > > +#define LINK_TO_DPI(ptr) SPICE_CONTAINEROF((ptr), DrawablePipeItem,
> > > > base)
> > > > +#define DRAWABLE_FOREACH_DPI_SAFE(drawable, link, next, dpi)
> > > > \
> > > > +    SAFE_FOREACH(link, next, drawable,  &(drawable)->pipes, dpi,
> > > > LINK_TO_DPI(link))
> > > > +
> > > > +
> > > >  struct DisplayChannelClient {
> > > >      CommonChannelClient common;
> > > >      SpiceImageCompression image_compression;
> > > > diff --git a/server/red_worker.c b/server/red_worker.c
> > > > index e63828b..6a29e00 100644
> > > > --- a/server/red_worker.c
> > > > +++ b/server/red_worker.c
> > > > @@ -79,9 +79,6 @@
> > > > 
> > > >  #define DISPLAY_FREE_LIST_DEFAULT_SIZE 128
> > > > 
> > > > -#define FPS_TEST_INTERVAL 1
> > > > -#define MAX_FPS 30
> > > > -
> > > >  #define ZLIB_DEFAULT_COMPRESSION_LEVEL 3
> > > >  #define MIN_GLZ_SIZE_FOR_ZLIB 100
> > > > 
> > > > @@ -286,8 +283,6 @@ static void red_draw_drawable(DisplayChannel
> > > > *display,
> > > > Drawable *item);
> > > >  static void red_update_area(DisplayChannel *display, const SpiceRect
> > > >  *area,
> > > > int surface_id);
> > > >  static void red_update_area_till(DisplayChannel *display, const
> > > >  SpiceRect
> > > > *area, int surface_id,
> > > >                                   Drawable *last);
> > > > -static void detach_stream(DisplayChannel *display, Stream *stream, int
> > > > detach_sized);
> > > > -static inline void display_channel_stream_maintenance(DisplayChannel
> > > > *display, Drawable *candidate, Drawable *sect);
> > > >  static inline void display_begin_send_message(RedChannelClient *rcc);
> > > >  static void red_release_glz(DisplayChannelClient *dcc);
> > > >  static void red_freeze_glz(DisplayChannelClient *dcc);
> > > > @@ -305,10 +300,6 @@ static void red_create_surface(DisplayChannel
> > > > *display,
> > > > uint32_t surface_id, uin
> > > >                                 uint32_t height, int32_t stride,
> > > > uint32_t
> > > > format,
> > > >                                 void *line_0, int data_is_valid, int
> > > > send_client);
> > > > 
> > > > -#define LINK_TO_DPI(ptr) SPICE_CONTAINEROF((ptr), DrawablePipeItem,
> > > > base)
> > > > -#define DRAWABLE_FOREACH_DPI_SAFE(drawable, link, next, dpi)          \
> > > > -    SAFE_FOREACH(link, next, drawable,  &(drawable)->pipes, dpi,
> > > > LINK_TO_DPI(link))
> > > > -
> > > > 
> > > >  #define LINK_TO_GLZ(ptr) SPICE_CONTAINEROF((ptr), RedGlzDrawable, \
> > > >                                             drawable_link)
> > > > @@ -1025,7 +1016,7 @@ static void __exclude_region(DisplayChannel
> > > > *display,
> > > > Ring *ring, TreeItem *item
> > > >              } else {
> > > >                  if (frame_candidate) {
> > > >                      Drawable *drawable = SPICE_CONTAINEROF(draw,
> > > >                      Drawable,
> > > > tree_item);
> > > > -                    display_channel_stream_maintenance(display,
> > > > frame_candidate, drawable);
> > > > +                    stream_maintenance(display, frame_candidate,
> > > > drawable);
> > > >                  }
> > > >                  region_exclude(&draw->base.rgn, &and_rgn);
> > > >              }
> > > > @@ -1130,8 +1121,8 @@ static void current_add_drawable(DisplayChannel
> > > > *display,
> > > >      drawable->refs++;
> > > >  }
> > > > 
> > > > -static void detach_stream(DisplayChannel *display, Stream *stream,
> > > > -                          int detach_sized)
> > > > +void detach_stream(DisplayChannel *display, Stream *stream,
> > > > +                   int detach_sized)
> > > >  {
> > > >      spice_assert(stream->current && stream->current->stream);
> > > >      spice_assert(stream->current->stream == stream);
> > > > @@ -1342,17 +1333,6 @@ static void
> > > > display_channel_streams_timeout(DisplayChannel *display)
> > > >      }
> > > >  }
> > > > 
> > > > -static Stream *display_channel_stream_try_new(DisplayChannel *display)
> > > > -{
> > > > -    Stream *stream;
> > > > -    if (!display->free_streams) {
> > > > -        return NULL;
> > > > -    }
> > > > -    stream = display->free_streams;
> > > > -    display->free_streams = display->free_streams->next;
> > > > -    return stream;
> > > > -}
> > > > -
> > > >  static uint64_t red_stream_get_initial_bit_rate(DisplayChannelClient
> > > >  *dcc,
> > > >                                                  Stream *stream)
> > > >  {
> > > > @@ -1528,47 +1508,6 @@ void dcc_create_stream(DisplayChannelClient *dcc,
> > > > Stream *stream)
> > > >  #endif
> > > >  }
> > > > 
> > > > -static void display_channel_create_stream(DisplayChannel *display,
> > > > Drawable
> > > > *drawable)
> > > > -{
> > > > -    DisplayChannelClient *dcc;
> > > > -    RingItem *dcc_ring_item, *next;
> > > > -    Stream *stream;
> > > > -    SpiceRect* src_rect;
> > > > -
> > > > -    spice_assert(!drawable->stream);
> > > > -
> > > > -    if (!(stream = display_channel_stream_try_new(display))) {
> > > > -        return;
> > > > -    }
> > > > -
> > > > -    spice_assert(drawable->red_drawable->type == QXL_DRAW_COPY);
> > > > -    src_rect = &drawable->red_drawable->u.copy.src_area;
> > > > -
> > > > -    ring_add(&display->streams, &stream->link);
> > > > -    stream->current = drawable;
> > > > -    stream->last_time = drawable->creation_time;
> > > > -    stream->width = src_rect->right - src_rect->left;
> > > > -    stream->height = src_rect->bottom - src_rect->top;
> > > > -    stream->dest_area = drawable->red_drawable->bbox;
> > > > -    stream->refs = 1;
> > > > -    SpiceBitmap *bitmap = &drawable->red_drawable->u.copy.src_bitmap
> > > > ->u.bitmap;
> > > > -    stream->top_down = !!(bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN);
> > > > -    drawable->stream = stream;
> > > > -    stream->input_fps = MAX_FPS;
> > > > -    stream->num_input_frames = 0;
> > > > -    stream->input_fps_start_time = drawable->creation_time;
> > > > -    display->streams_size_total += stream->width * stream->height;
> > > > -    display->stream_count++;
> > > > -    FOREACH_DCC(display, dcc_ring_item, next, dcc) {
> > > > -        dcc_create_stream(dcc, stream);
> > > > -    }
> > > > -    spice_debug("stream %d %dx%d (%d, %d) (%d, %d)",
> > > > -                (int)(stream - display->streams_buf), stream->width,
> > > > -                stream->height, stream->dest_area.left, stream
> > > > ->dest_area.top,
> > > > -                stream->dest_area.right, stream->dest_area.bottom);
> > > > -    return;
> > > > -}
> > > > -
> > > >  static void dcc_create_all_streams(DisplayChannelClient *dcc)
> > > >  {
> > > >      Ring *ring = &DCC_TO_DC(dcc)->streams;
> > > > @@ -1613,256 +1552,6 @@ static void
> > > > dcc_destroy_stream_agents(DisplayChannelClient *dcc)
> > > >      }
> > > >  }
> > > > 
> > > > -static int is_next_stream_frame(DisplayChannel *display,
> > > > -                                const Drawable *candidate,
> > > > -                                const int other_src_width,
> > > > -                                const int other_src_height,
> > > > -                                const SpiceRect *other_dest,
> > > > -                                const red_time_t other_time,
> > > > -                                const Stream *stream,
> > > > -                                int container_candidate_allowed)
> > > > -{
> > > > -    RedDrawable *red_drawable;
> > > > -    int is_frame_container = FALSE;
> > > > -
> > > > -    if (!candidate->streamable) {
> > > > -        return STREAM_FRAME_NONE;
> > > > -    }
> > > > -
> > > > -    if (candidate->creation_time - other_time >
> > > > -            (stream ? RED_STREAM_CONTINUS_MAX_DELTA :
> > > > RED_STREAM_DETACTION_MAX_DELTA)) {
> > > > -        return STREAM_FRAME_NONE;
> > > > -    }
> > > > -
> > > > -    red_drawable = candidate->red_drawable;
> > > > -    if (!container_candidate_allowed) {
> > > > -        SpiceRect* candidate_src;
> > > > -
> > > > -        if (!rect_is_equal(&red_drawable->bbox, other_dest)) {
> > > > -            return STREAM_FRAME_NONE;
> > > > -        }
> > > > -
> > > > -        candidate_src = &red_drawable->u.copy.src_area;
> > > > -        if (candidate_src->right - candidate_src->left !=
> > > > other_src_width
> > > > > > 
> > > > -            candidate_src->bottom - candidate_src->top !=
> > > > other_src_height)
> > > > {
> > > > -            return STREAM_FRAME_NONE;
> > > > -        }
> > > > -    } else {
> > > > -        if (rect_contains(&red_drawable->bbox, other_dest)) {
> > > > -            int candidate_area = rect_get_area(&red_drawable->bbox);
> > > > -            int other_area = rect_get_area(other_dest);
> > > > -            /* do not stream drawables that are significantly
> > > > -             * bigger than the original frame */
> > > > -            if (candidate_area > 2 * other_area) {
> > > > -                spice_debug("too big candidate:");
> > > > -                spice_debug("prev box ==>");
> > > > -                rect_debug(other_dest);
> > > > -                spice_debug("new box ==>");
> > > > -                rect_debug(&red_drawable->bbox);
> > > > -                return STREAM_FRAME_NONE;
> > > > -            }
> > > > -
> > > > -            if (candidate_area > other_area) {
> > > > -                is_frame_container = TRUE;
> > > > -            }
> > > > -        } else {
> > > > -            return STREAM_FRAME_NONE;
> > > > -        }
> > > > -    }
> > > > -
> > > > -    if (stream) {
> > > > -        SpiceBitmap *bitmap =
> > > > &red_drawable->u.copy.src_bitmap->u.bitmap;
> > > > -        if (stream->top_down != !!(bitmap->flags &
> > > > SPICE_BITMAP_FLAGS_TOP_DOWN)) {
> > > > -            return STREAM_FRAME_NONE;
> > > > -        }
> > > > -    }
> > > > -    if (is_frame_container) {
> > > > -        return STREAM_FRAME_CONTAINER;
> > > > -    } else {
> > > > -        return STREAM_FRAME_NATIVE;
> > > > -    }
> > > > -}
> > > > -
> > > > -static void before_reattach_stream(DisplayChannel *display,
> > > > -                                   Stream *stream, Drawable *new_frame)
> > > > -{
> > > > -    DrawablePipeItem *dpi;
> > > > -    DisplayChannelClient *dcc;
> > > > -    int index;
> > > > -    StreamAgent *agent;
> > > > -    RingItem *ring_item, *next;
> > > > -
> > > > -    spice_return_if_fail(stream->current);
> > > > -
> > > > -    if (!red_channel_is_connected(RED_CHANNEL(display))) {
> > > > -        return;
> > > > -    }
> > > > -
> > > > -    if (new_frame->process_commands_generation == stream->current
> > > > ->process_commands_generation) {
> > > > -        spice_debug("ignoring drop, same process_commands_generation as
> > > > previous frame");
> > > > -        return;
> > > > -    }
> > > > -
> > > > -    index = get_stream_id(display, stream);
> > > > -    DRAWABLE_FOREACH_DPI_SAFE(stream->current, ring_item, next, dpi) {
> > > > -        dcc = dpi->dcc;
> > > > -        agent = &dcc->stream_agents[index];
> > > > -
> > > > -        if (!dcc->use_mjpeg_encoder_rate_control &&
> > > > -            !dcc->common.is_low_bandwidth) {
> > > > -            continue;
> > > > -        }
> > > > -
> > > > -        if (pipe_item_is_linked(&dpi->dpi_pipe_item)) {
> > > > -#ifdef STREAM_STATS
> > > > -            agent->stats.num_drops_pipe++;
> > > > -#endif
> > > > -            if (dcc->use_mjpeg_encoder_rate_control) {
> > > > -                mjpeg_encoder_notify_server_frame_drop(agent
> > > > ->mjpeg_encoder);
> > > > -            } else {
> > > > -                ++agent->drops;
> > > > -            }
> > > > -        }
> > > > -    }
> > > > -
> > > > -
> > > > -    FOREACH_DCC(display, ring_item, next, dcc) {
> > > > -        double drop_factor;
> > > > -
> > > > -        agent = &dcc->stream_agents[index];
> > > > -
> > > > -        if (dcc->use_mjpeg_encoder_rate_control) {
> > > > -            continue;
> > > > -        }
> > > > -        if (agent->frames / agent->fps < FPS_TEST_INTERVAL) {
> > > > -            agent->frames++;
> > > > -            continue;
> > > > -        }
> > > > -        drop_factor = ((double)agent->frames - (double)agent->drops) /
> > > > -            (double)agent->frames;
> > > > -        spice_debug("stream %d: #frames %u #drops %u", index, agent
> > > > ->frames, agent->drops);
> > > > -        if (drop_factor == 1) {
> > > > -            if (agent->fps < MAX_FPS) {
> > > > -                agent->fps++;
> > > > -                spice_debug("stream %d: fps++ %u", index, agent->fps);
> > > > -            }
> > > > -        } else if (drop_factor < 0.9) {
> > > > -            if (agent->fps > 1) {
> > > > -                agent->fps--;
> > > > -                spice_debug("stream %d: fps--%u", index, agent->fps);
> > > > -            }
> > > > -        }
> > > > -        agent->frames = 1;
> > > > -        agent->drops = 0;
> > > > -    }
> > > > -}
> > > > -
> > > > -static void update_copy_graduality(DisplayChannel *display, Drawable
> > > > *drawable)
> > > > -{
> > > > -    SpiceBitmap *bitmap;
> > > > -    spice_return_if_fail(drawable->red_drawable->type ==
> > > > QXL_DRAW_COPY);
> > > > -
> > > > -    if (display->stream_video != SPICE_STREAM_VIDEO_FILTER) {
> > > > -        drawable->copy_bitmap_graduality = BITMAP_GRADUAL_INVALID;
> > > > -        return;
> > > > -    }
> > > > -
> > > > -    if (drawable->copy_bitmap_graduality != BITMAP_GRADUAL_INVALID) {
> > > > -        return; // already set
> > > > -    }
> > > > -
> > > > -    bitmap = &drawable->red_drawable->u.copy.src_bitmap->u.bitmap;
> > > > -
> > > > -    if (!bitmap_fmt_has_graduality(bitmap->format) ||
> > > > bitmap_has_extra_stride(bitmap) ||
> > > > -        (bitmap->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE)) {
> > > > -        drawable->copy_bitmap_graduality = BITMAP_GRADUAL_NOT_AVAIL;
> > > > -    } else  {
> > > > -        drawable->copy_bitmap_graduality =
> > > > bitmap_get_graduality_level(bitmap);
> > > > -    }
> > > > -}
> > > > -
> > > > -static int is_stream_start(Drawable *drawable)
> > > > -{
> > > > -    return ((drawable->frames_count >=
> > > > RED_STREAM_FRAMES_START_CONDITION)
> > > > &&
> > > > -            (drawable->gradual_frames_count >=
> > > > -            (RED_STREAM_GRADUAL_FRAMES_START_CONDITION * drawable
> > > > ->frames_count)));
> > > > -}
> > > > -
> > > > -// returns whether a stream was created
> > > > -static int display_channel_stream_add_frame(DisplayChannel *display,
> > > > -                                            Drawable *frame_drawable,
> > > > -                                            int frames_count,
> > > > -                                            int gradual_frames_count,
> > > > -                                            int last_gradual_frame)
> > > > -{
> > > > -    update_copy_graduality(display, frame_drawable);
> > > > -    frame_drawable->frames_count = frames_count + 1;
> > > > -    frame_drawable->gradual_frames_count  = gradual_frames_count;
> > > > -
> > > > -    if (frame_drawable->copy_bitmap_graduality != BITMAP_GRADUAL_LOW) {
> > > > -        if ((frame_drawable->frames_count - last_gradual_frame) >
> > > > -            RED_STREAM_FRAMES_RESET_CONDITION) {
> > > > -            frame_drawable->frames_count = 1;
> > > > -            frame_drawable->gradual_frames_count = 1;
> > > > -        } else {
> > > > -            frame_drawable->gradual_frames_count++;
> > > > -        }
> > > > -
> > > > -        frame_drawable->last_gradual_frame =
> > > > frame_drawable->frames_count;
> > > > -    } else {
> > > > -        frame_drawable->last_gradual_frame = last_gradual_frame;
> > > > -    }
> > > > -
> > > > -    if (is_stream_start(frame_drawable)) {
> > > > -        display_channel_create_stream(display, frame_drawable);
> > > > -        return TRUE;
> > > > -    }
> > > > -    return FALSE;
> > > > -}
> > > > -
> > > > -static void display_channel_stream_maintenance(DisplayChannel *display,
> > > > -                                               Drawable *candidate,
> > > > Drawable *prev)
> > > > -{
> > > > -    int is_next_frame;
> > > > -
> > > > -    if (candidate->stream) {
> > > > -        return;
> > > > -    }
> > > > -
> > > > -    if (prev->stream) {
> > > > -        Stream *stream = prev->stream;
> > > > -
> > > > -        is_next_frame = is_next_stream_frame(display, candidate,
> > > > -                                             stream->width,
> > > > stream->height,
> > > > -                                             &stream->dest_area, stream
> > > > ->last_time,
> > > > -                                             stream, TRUE);
> > > > -        if (is_next_frame != STREAM_FRAME_NONE) {
> > > > -            before_reattach_stream(display, stream, candidate);
> > > > -            detach_stream(display, stream, FALSE);
> > > > -            prev->streamable = FALSE; //prevent item trace
> > > > -            attach_stream(display, candidate, stream);
> > > > -            if (is_next_frame == STREAM_FRAME_CONTAINER) {
> > > > -                candidate->sized_stream = stream;
> > > > -            }
> > > > -        }
> > > > -    } else if (candidate->streamable) {
> > > > -        SpiceRect* prev_src = &prev->red_drawable->u.copy.src_area;
> > > > -
> > > > -        is_next_frame =
> > > > -            is_next_stream_frame(display, candidate, prev_src->right -
> > > > prev_src->left,
> > > > -                                 prev_src->bottom - prev_src->top,
> > > > -                                 &prev->red_drawable->bbox, prev
> > > > ->creation_time,
> > > > -                                 prev->stream,
> > > > -                                 FALSE);
> > > > -        if (is_next_frame != STREAM_FRAME_NONE) {
> > > > -            display_channel_stream_add_frame(display, candidate,
> > > > -                                             prev->frames_count,
> > > > -                                             prev
> > > > ->gradual_frames_count,
> > > > -                                             prev->last_gradual_frame);
> > > > -        }
> > > > -    }
> > > > -}
> > > > -
> > > >  static inline int red_current_add_equal(DisplayChannel *display,
> > > >  DrawItem
> > > > *item, TreeItem *other)
> > > >  {
> > > >      DrawItem *other_draw_item;
> > > > @@ -1884,7 +1573,7 @@ static inline int
> > > > red_current_add_equal(DisplayChannel
> > > > *display, DrawItem *item,
> > > >      if (item->effect == QXL_EFFECT_OPAQUE) {
> > > >          int add_after = !!other_drawable->stream &&
> > > >                         
> > > >  is_drawable_independent_from_surfaces(drawable);
> > > > -        display_channel_stream_maintenance(display, drawable,
> > > > other_drawable);
> > > > +        stream_maintenance(display, drawable, other_drawable);
> > > >          current_add_drawable(display, drawable, &other->siblings_link);
> > > >          other_drawable->refs++;
> > > >          current_remove_drawable(display, other_drawable);
> > > > @@ -1958,61 +1647,6 @@ static inline int
> > > > red_current_add_equal(DisplayChannel *display, DrawItem *item,
> > > >      return FALSE;
> > > >  }
> > > > 
> > > > -#define FOREACH_STREAMS(display, item)                  \
> > > > -    for (item = ring_get_head(&(display)->streams);     \
> > > > -         item != NULL;                                  \
> > > > -         item = ring_next(&(display)->streams, item))
> > > > -
> > > > -static void red_use_stream_trace(DisplayChannel *display, Drawable
> > > > *drawable)
> > > > -{
> > > > -    ItemTrace *trace;
> > > > -    ItemTrace *trace_end;
> > > > -    RingItem *item;
> > > > -
> > > > -    if (drawable->stream || !drawable->streamable || drawable
> > > > ->frames_count) {
> > > > -        return;
> > > > -    }
> > > > -
> > > > -    FOREACH_STREAMS(display, item) {
> > > > -        Stream *stream = SPICE_CONTAINEROF(item, Stream, link);
> > > > -        int is_next_frame = is_next_stream_frame(display,
> > > > -                                                 drawable,
> > > > -                                                 stream->width,
> > > > -                                                 stream->height,
> > > > -                                                 &stream->dest_area,
> > > > -                                                 stream->last_time,
> > > > -                                                 stream,
> > > > -                                                 TRUE);
> > > > -        if (is_next_frame != STREAM_FRAME_NONE) {
> > > > -            if (stream->current) {
> > > > -                stream->current->streamable = FALSE; //prevent item
> > > > trace
> > > > -                before_reattach_stream(display, stream, drawable);
> > > > -                detach_stream(display, stream, FALSE);
> > > > -            }
> > > > -            attach_stream(display, drawable, stream);
> > > > -            if (is_next_frame == STREAM_FRAME_CONTAINER) {
> > > > -                drawable->sized_stream = stream;
> > > > -            }
> > > > -            return;
> > > > -        }
> > > > -    }
> > > > -
> > > > -    trace = display->items_trace;
> > > > -    trace_end = trace + NUM_TRACE_ITEMS;
> > > > -    for (; trace < trace_end; trace++) {
> > > > -        if (is_next_stream_frame(display, drawable, trace->width, trace
> > > > ->height,
> > > > -                                       &trace->dest_area, trace->time,
> > > > NULL, FALSE) !=
> > > > -                                       STREAM_FRAME_NONE) {
> > > > -            if (display_channel_stream_add_frame(display, drawable,
> > > > -                                                 trace->frames_count,
> > > > -                                                 trace
> > > > ->gradual_frames_count,
> > > > -                                                 trace
> > > > ->last_gradual_frame)) {
> > > > -                return;
> > > > -            }
> > > > -        }
> > > > -    }
> > > > -}
> > > > -
> > > >  static int current_add(DisplayChannel *display, Ring *ring, Drawable
> > > > *drawable)
> > > >  {
> > > >      DrawItem *item = &drawable->tree_item;
> > > > @@ -2109,7 +1743,7 @@ static int current_add(DisplayChannel *display,
> > > > Ring
> > > > *ring, Drawable *drawable)
> > > >      if (item->effect == QXL_EFFECT_OPAQUE) {
> > > >          region_or(&exclude_rgn, &item->base.rgn);
> > > >          exclude_region(display, ring, exclude_base, &exclude_rgn, NULL,
> > > > drawable);
> > > > -        red_use_stream_trace(display, drawable);
> > > > +        stream_trace_update(display, drawable);
> > > >          streams_update_visible_region(display, drawable);
> > > >          /*
> > > >           * Performing the insertion after exclude_region for
> > > > diff --git a/server/stream.c b/server/stream.c
> > > > index d61cec1..54f81a8 100644
> > > > --- a/server/stream.c
> > > > +++ b/server/stream.c
> > > > @@ -21,6 +21,12 @@
> > > >  #include "stream.h"
> > > >  #include "display-channel.h"
> > > > 
> > > > +#define FPS_TEST_INTERVAL 1
> > > > +#define FOREACH_STREAMS(display, item)                  \
> > > > +    for (item = ring_get_head(&(display)->streams);     \
> > > > +         item != NULL;                                  \
> > > > +         item = ring_next(&(display)->streams, item))
> > > > +
> > > >  void stream_agent_stats_print(StreamAgent *agent)
> > > >  {
> > > >  #ifdef STREAM_STATS
> > > > @@ -138,3 +144,356 @@ StreamClipItem
> > > > *stream_clip_item_new(DisplayChannelClient* dcc, StreamAgent *age
> > > >      item->refs = 1;
> > > >      return item;
> > > >  }
> > > > +
> > > > +static int is_stream_start(Drawable *drawable)
> > > > +{
> > > > +    return ((drawable->frames_count >=
> > > > RED_STREAM_FRAMES_START_CONDITION)
> > > > &&
> > > > +            (drawable->gradual_frames_count >=
> > > > +             (RED_STREAM_GRADUAL_FRAMES_START_CONDITION * drawable
> > > > ->frames_count)));
> > > > +}
> > > > +
> > > > +static void update_copy_graduality(DisplayChannel *display, Drawable
> > > > *drawable)
> > > > +{
> > > > +    SpiceBitmap *bitmap;
> > > > +    spice_return_if_fail(drawable->red_drawable->type ==
> > > > QXL_DRAW_COPY);
> > > > +
> > > > +    if (display->stream_video != SPICE_STREAM_VIDEO_FILTER) {
> > > > +        drawable->copy_bitmap_graduality = BITMAP_GRADUAL_INVALID;
> > > > +        return;
> > > > +    }
> > > > +
> > > > +    if (drawable->copy_bitmap_graduality != BITMAP_GRADUAL_INVALID) {
> > > > +        return; // already set
> > > > +    }
> > > > +
> > > > +    bitmap = &drawable->red_drawable->u.copy.src_bitmap->u.bitmap;
> > > > +
> > > > +    if (!bitmap_fmt_has_graduality(bitmap->format) ||
> > > > bitmap_has_extra_stride(bitmap) ||
> > > > +        (bitmap->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE)) {
> > > > +        drawable->copy_bitmap_graduality = BITMAP_GRADUAL_NOT_AVAIL;
> > > > +    } else  {
> > > > +        drawable->copy_bitmap_graduality =
> > > > bitmap_get_graduality_level(bitmap);
> > > > +    }
> > > > +}
> > > > +
> > > > +static int is_next_stream_frame(DisplayChannel *display,
> > > > +                                const Drawable *candidate,
> > > > +                                const int other_src_width,
> > > > +                                const int other_src_height,
> > > > +                                const SpiceRect *other_dest,
> > > > +                                const red_time_t other_time,
> > > > +                                const Stream *stream,
> > > > +                                int container_candidate_allowed)
> > > > +{
> > > > +    RedDrawable *red_drawable;
> > > > +    int is_frame_container = FALSE;
> > > > +
> > > > +    if (!candidate->streamable) {
> > > > +        return STREAM_FRAME_NONE;
> > > > +    }
> > > > +
> > > > +    if (candidate->creation_time - other_time >
> > > > +            (stream ? RED_STREAM_CONTINUS_MAX_DELTA :
> > > > RED_STREAM_DETACTION_MAX_DELTA)) {
> > > > +        return STREAM_FRAME_NONE;
> > > > +    }
> > > > +
> > > > +    red_drawable = candidate->red_drawable;
> > > > +    if (!container_candidate_allowed) {
> > > > +        SpiceRect* candidate_src;
> > > > +
> > > > +        if (!rect_is_equal(&red_drawable->bbox, other_dest)) {
> > > > +            return STREAM_FRAME_NONE;
> > > > +        }
> > > > +
> > > > +        candidate_src = &red_drawable->u.copy.src_area;
> > > > +        if (candidate_src->right - candidate_src->left !=
> > > > other_src_width
> > > > > > 
> > > > +            candidate_src->bottom - candidate_src->top !=
> > > > other_src_height)
> > > > {
> > > > +            return STREAM_FRAME_NONE;
> > > > +        }
> > > > +    } else {
> > > > +        if (rect_contains(&red_drawable->bbox, other_dest)) {
> > > > +            int candidate_area = rect_get_area(&red_drawable->bbox);
> > > > +            int other_area = rect_get_area(other_dest);
> > > > +            /* do not stream drawables that are significantly
> > > > +             * bigger than the original frame */
> > > > +            if (candidate_area > 2 * other_area) {
> > > > +                spice_debug("too big candidate:");
> > > > +                spice_debug("prev box ==>");
> > > > +                rect_debug(other_dest);
> > > > +                spice_debug("new box ==>");
> > > > +                rect_debug(&red_drawable->bbox);
> > > > +                return STREAM_FRAME_NONE;
> > > > +            }
> > > > +
> > > > +            if (candidate_area > other_area) {
> > > > +                is_frame_container = TRUE;
> > > > +            }
> > > > +        } else {
> > > > +            return STREAM_FRAME_NONE;
> > > > +        }
> > > > +    }
> > > > +
> > > > +    if (stream) {
> > > > +        SpiceBitmap *bitmap =
> > > > &red_drawable->u.copy.src_bitmap->u.bitmap;
> > > > +        if (stream->top_down != !!(bitmap->flags &
> > > > SPICE_BITMAP_FLAGS_TOP_DOWN)) {
> > > > +            return STREAM_FRAME_NONE;
> > > > +        }
> > > > +    }
> > > > +    if (is_frame_container) {
> > > > +        return STREAM_FRAME_CONTAINER;
> > > > +    } else {
> > > > +        return STREAM_FRAME_NATIVE;
> > > > +    }
> > > > +}
> > > > +
> > > > +static void before_reattach_stream(DisplayChannel *display,
> > > > +                                   Stream *stream, Drawable *new_frame)
> > > > +{
> > > > +    DrawablePipeItem *dpi;
> > > > +    DisplayChannelClient *dcc;
> > > > +    int index;
> > > > +    StreamAgent *agent;
> > > > +    RingItem *ring_item, *next;
> > > > +
> > > > +    spice_return_if_fail(stream->current);
> > > > +
> > > > +    if (!red_channel_is_connected(RED_CHANNEL(display))) {
> > > > +        return;
> > > > +    }
> > > > +
> > > > +    if (new_frame->process_commands_generation == stream->current
> > > > ->process_commands_generation) {
> > > > +        spice_debug("ignoring drop, same process_commands_generation as
> > > > previous frame");
> > > > +        return;
> > > > +    }
> > > > +
> > > > +    index = get_stream_id(display, stream);
> > > > +    DRAWABLE_FOREACH_DPI_SAFE(stream->current, ring_item, next, dpi) {
> > > > +        dcc = dpi->dcc;
> > > > +        agent = &dcc->stream_agents[index];
> > > > +
> > > > +        if (!dcc->use_mjpeg_encoder_rate_control &&
> > > > +            !dcc->common.is_low_bandwidth) {
> > > > +            continue;
> > > > +        }
> > > > +
> > > > +        if (pipe_item_is_linked(&dpi->dpi_pipe_item)) {
> > > > +#ifdef STREAM_STATS
> > > > +            agent->stats.num_drops_pipe++;
> > > > +#endif
> > > > +            if (dcc->use_mjpeg_encoder_rate_control) {
> > > > +                mjpeg_encoder_notify_server_frame_drop(agent
> > > > ->mjpeg_encoder);
> > > > +            } else {
> > > > +                ++agent->drops;
> > > > +            }
> > > > +        }
> > > > +    }
> > > > +
> > > > +
> > > > +    FOREACH_DCC(display, ring_item, next, dcc) {
> > > > +        double drop_factor;
> > > > +
> > > > +        agent = &dcc->stream_agents[index];
> > > > +
> > > > +        if (dcc->use_mjpeg_encoder_rate_control) {
> > > > +            continue;
> > > > +        }
> > > > +        if (agent->frames / agent->fps < FPS_TEST_INTERVAL) {
> > > > +            agent->frames++;
> > > > +            continue;
> > > > +        }
> > > > +        drop_factor = ((double)agent->frames - (double)agent->drops) /
> > > > +            (double)agent->frames;
> > > > +        spice_debug("stream %d: #frames %u #drops %u", index, agent
> > > > ->frames, agent->drops);
> > > > +        if (drop_factor == 1) {
> > > > +            if (agent->fps < MAX_FPS) {
> > > > +                agent->fps++;
> > > > +                spice_debug("stream %d: fps++ %u", index, agent->fps);
> > > > +            }
> > > > +        } else if (drop_factor < 0.9) {
> > > > +            if (agent->fps > 1) {
> > > > +                agent->fps--;
> > > > +                spice_debug("stream %d: fps--%u", index, agent->fps);
> > > > +            }
> > > > +        }
> > > > +        agent->frames = 1;
> > > > +        agent->drops = 0;
> > > > +    }
> > > > +}
> > > > +
> > > > +static Stream *display_channel_stream_try_new(DisplayChannel *display)
> > > > +{
> > > > +    Stream *stream;
> > > > +    if (!display->free_streams) {
> > > > +        return NULL;
> > > > +    }
> > > > +    stream = display->free_streams;
> > > > +    display->free_streams = display->free_streams->next;
> > > > +    return stream;
> > > > +}
> > > > +
> > > > +static void display_channel_create_stream(DisplayChannel *display,
> > > > Drawable
> > > > *drawable)
> > > > +{
> > > > +    DisplayChannelClient *dcc;
> > > > +    RingItem *dcc_ring_item, *next;
> > > > +    Stream *stream;
> > > > +    SpiceRect* src_rect;
> > > > +
> > > > +    spice_assert(!drawable->stream);
> > > > +
> > > > +    if (!(stream = display_channel_stream_try_new(display))) {
> > > > +        return;
> > > > +    }
> > > > +
> > > > +    spice_assert(drawable->red_drawable->type == QXL_DRAW_COPY);
> > > > +    src_rect = &drawable->red_drawable->u.copy.src_area;
> > > > +
> > > > +    ring_add(&display->streams, &stream->link);
> > > > +    stream->current = drawable;
> > > > +    stream->last_time = drawable->creation_time;
> > > > +    stream->width = src_rect->right - src_rect->left;
> > > > +    stream->height = src_rect->bottom - src_rect->top;
> > > > +    stream->dest_area = drawable->red_drawable->bbox;
> > > > +    stream->refs = 1;
> > > > +    SpiceBitmap *bitmap = &drawable->red_drawable->u.copy.src_bitmap
> > > > ->u.bitmap;
> > > > +    stream->top_down = !!(bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN);
> > > > +    drawable->stream = stream;
> > > > +    stream->input_fps = MAX_FPS;
> > > > +    stream->num_input_frames = 0;
> > > > +    stream->input_fps_start_time = drawable->creation_time;
> > > > +    display->streams_size_total += stream->width * stream->height;
> > > > +    display->stream_count++;
> > > > +    FOREACH_DCC(display, dcc_ring_item, next, dcc) {
> > > > +        dcc_create_stream(dcc, stream);
> > > > +    }
> > > > +    spice_debug("stream %d %dx%d (%d, %d) (%d, %d)",
> > > > +                (int)(stream - display->streams_buf), stream->width,
> > > > +                stream->height, stream->dest_area.left, stream
> > > > ->dest_area.top,
> > > > +                stream->dest_area.right, stream->dest_area.bottom);
> > > > +    return;
> > > > +}
> > > > +
> > > > +// returns whether a stream was created
> > > > +static int stream_add_frame(DisplayChannel *display,
> > > > +                            Drawable *frame_drawable,
> > > > +                            int frames_count,
> > > > +                            int gradual_frames_count,
> > > > +                            int last_gradual_frame)
> > > > +{
> > > > +    update_copy_graduality(display, frame_drawable);
> > > > +    frame_drawable->frames_count = frames_count + 1;
> > > > +    frame_drawable->gradual_frames_count  = gradual_frames_count;
> > > > +
> > > > +    if (frame_drawable->copy_bitmap_graduality != BITMAP_GRADUAL_LOW) {
> > > > +        if ((frame_drawable->frames_count - last_gradual_frame) >
> > > > +            RED_STREAM_FRAMES_RESET_CONDITION) {
> > > > +            frame_drawable->frames_count = 1;
> > > > +            frame_drawable->gradual_frames_count = 1;
> > > > +        } else {
> > > > +            frame_drawable->gradual_frames_count++;
> > > > +        }
> > > > +
> > > > +        frame_drawable->last_gradual_frame =
> > > > frame_drawable->frames_count;
> > > > +    } else {
> > > > +        frame_drawable->last_gradual_frame = last_gradual_frame;
> > > > +    }
> > > > +
> > > > +    if (is_stream_start(frame_drawable)) {
> > > > +        display_channel_create_stream(display, frame_drawable);
> > > > +        return TRUE;
> > > > +    }
> > > > +    return FALSE;
> > > > +}
> > > > +
> > > > +/* TODO: document the difference between the 2 functions below */
> > > > +void stream_trace_update(DisplayChannel *display, Drawable *drawable)
> > > > +{
> > > > +    ItemTrace *trace;
> > > > +    ItemTrace *trace_end;
> > > > +    RingItem *item;
> > > > +
> > > > +    if (drawable->stream || !drawable->streamable || drawable
> > > > ->frames_count) {
> > > > +        return;
> > > > +    }
> > > > +
> > > > +    FOREACH_STREAMS(display, item) {
> > > > +        Stream *stream = SPICE_CONTAINEROF(item, Stream, link);
> > > > +        int is_next_frame = is_next_stream_frame(display,
> > > > +                                                 drawable,
> > > > +                                                 stream->width,
> > > > +                                                 stream->height,
> > > > +                                                 &stream->dest_area,
> > > > +                                                 stream->last_time,
> > > > +                                                 stream,
> > > > +                                                 TRUE);
> > > > +        if (is_next_frame != STREAM_FRAME_NONE) {
> > > > +            if (stream->current) {
> > > > +                stream->current->streamable = FALSE; //prevent item
> > > > trace
> > > > +                before_reattach_stream(display, stream, drawable);
> > > > +                detach_stream(display, stream, FALSE);
> > > > +            }
> > > > +            attach_stream(display, drawable, stream);
> > > > +            if (is_next_frame == STREAM_FRAME_CONTAINER) {
> > > > +                drawable->sized_stream = stream;
> > > > +            }
> > > > +            return;
> > > > +        }
> > > > +    }
> > > > +
> > > > +    trace = display->items_trace;
> > > > +    trace_end = trace + NUM_TRACE_ITEMS;
> > > > +    for (; trace < trace_end; trace++) {
> > > > +        if (is_next_stream_frame(display, drawable, trace->width, trace
> > > > ->height,
> > > > +                                       &trace->dest_area, trace->time,
> > > > NULL, FALSE) !=
> > > > +                                       STREAM_FRAME_NONE) {
> > > > +            if (stream_add_frame(display, drawable,
> > > > +                                 trace->frames_count,
> > > > +                                 trace->gradual_frames_count,
> > > > +                                 trace->last_gradual_frame)) {
> > > > +                return;
> > > > +            }
> > > > +        }
> > > > +    }
> > > > +}
> > > > +
> > > > +void stream_maintenance(DisplayChannel *display,
> > > > +                        Drawable *candidate, Drawable *prev)
> > > > +{
> > > > +    int is_next_frame;
> > > > +
> > > > +    if (candidate->stream) {
> > > > +        return;
> > > > +    }
> > > > +
> > > > +    if (prev->stream) {
> > > > +        Stream *stream = prev->stream;
> > > > +
> > > > +        is_next_frame = is_next_stream_frame(display, candidate,
> > > > +                                             stream->width,
> > > > stream->height,
> > > > +                                             &stream->dest_area, stream
> > > > ->last_time,
> > > > +                                             stream, TRUE);
> > > > +        if (is_next_frame != STREAM_FRAME_NONE) {
> > > > +            before_reattach_stream(display, stream, candidate);
> > > > +            detach_stream(display, stream, FALSE);
> > > > +            prev->streamable = FALSE; //prevent item trace
> > > > +            attach_stream(display, candidate, stream);
> > > > +            if (is_next_frame == STREAM_FRAME_CONTAINER) {
> > > > +                candidate->sized_stream = stream;
> > > > +            }
> > > > +        }
> > > > +    } else if (candidate->streamable) {
> > > > +        SpiceRect* prev_src = &prev->red_drawable->u.copy.src_area;
> > > > +
> > > > +        is_next_frame =
> > > > +            is_next_stream_frame(display, candidate, prev_src->right -
> > > > prev_src->left,
> > > > +                                 prev_src->bottom - prev_src->top,
> > > > +                                 &prev->red_drawable->bbox, prev
> > > > ->creation_time,
> > > > +                                 prev->stream,
> > > > +                                 FALSE);
> > > > +        if (is_next_frame != STREAM_FRAME_NONE) {
> > > > +            stream_add_frame(display, candidate,
> > > > +                             prev->frames_count,
> > > > +                             prev->gradual_frames_count,
> > > > +                             prev->last_gradual_frame);
> > > > +        }
> > > > +    }
> > > > +}
> > > > diff --git a/server/stream.h b/server/stream.h
> > > > index 4704937..bf78137 100644
> > > > --- a/server/stream.h
> > > > +++ b/server/stream.h
> > > > @@ -39,6 +39,7 @@
> > > >  #define RED_STREAM_CLIENT_REPORT_TIMEOUT 1000 // milliseconds
> > > >  #define RED_STREAM_DEFAULT_HIGH_START_BIT_RATE (10 * 1024 * 1024) //
> > > >  10Mbps
> > > >  #define RED_STREAM_DEFAULT_LOW_START_BIT_RATE (2.5 * 1024 * 1024) //
> > > > 2.5Mbps
> > > > +#define MAX_FPS 30
> > > > 
> > > >  /* move back to display_channel once struct private */
> > > >  typedef struct DisplayChannel DisplayChannel;
> > > > @@ -143,5 +144,13 @@ void                  stream_unref
> > > >              (DisplayChan
> > > >  void                  stream_agent_unref
> > > >  (DisplayChannel *display,
> > > >                                                                      
> > > >  StreamAgent *agent);
> > > >  void                  stream_agent_stats_print
> > > >  (StreamAgent *agent);
> > > > +void                  stream_trace_update
> > > >  (DisplayChannel *display,
> > > > +
> > > >  Drawable *drawable);
> > > > +void                  stream_maintenance
> > > >  (DisplayChannel *display,
> > > > +
> > > >  Drawable *candidate,
> > > > +
> > > >  Drawable *prev);
> > > > +
> > > > +void attach_stream(DisplayChannel *display, Drawable *drawable, Stream
> > > > *stream);
> > > > +void detach_stream(DisplayChannel *display, Stream *stream, int
> > > > detach_sized);
> > > > 
> > > >  #endif /* STREAM_H */
> > > > --
> > > > 2.4.3
> > > > 
> > > > _______________________________________________
> > > > Spice-devel mailing list
> > > > Spice-devel at lists.freedesktop.org
> > > > http://lists.freedesktop.org/mailman/listinfo/spice-devel
> > > 
> > > The patch is huge, but it's pretty much just moving things around.
> > > From a few simple tests (both with Linux and Windows guests) it
> > > doesn't seem to break anything.
> > > ACK.
> > 
> > 
> > I just noticed that this (split) commit now has basically the same name as
> > patch
> > 01/11 in this same series. Should I change the commit log?
> > 
> > 
> 
> Well, describing the difference between the first set of function and these
> would be helpful.
> 
> Frediano


How about "Move stream creation and maintenance functions to stream.[ch]"?


More information about the Spice-devel mailing list