[Spice-devel] [PATCH 5/9] worker: move stream_agent_stop and friends

Jonathon Jongsma jjongsma at redhat.com
Tue Nov 17 12:02:48 PST 2015


ACK

On Tue, 2015-11-17 at 16:37 +0000, Frediano Ziglio wrote:
> From: Marc-André Lureau <marcandre.lureau at gmail.com>
> 
> ---
>  server/display-channel.h |   2 +
>  server/red_worker.c      | 178 +---------------------------------------------
> -
>  server/stream.c          | 174 +++++++++++++++++++++++++++++++++++++++++++++
>  server/stream.h          |   3 +
>  4 files changed, 180 insertions(+), 177 deletions(-)
> 
> diff --git a/server/display-channel.h b/server/display-channel.h
> index edbd4b9..ae8a900 100644
> --- a/server/display-channel.h
> +++ b/server/display-channel.h
> @@ -252,6 +252,8 @@ void                       dcc_push_destroy_surface       
>            (DisplayCha
>                                                                       
>  uint32_t surface_id);
>  void                       dcc_add_stream_agent_clip                
>  (DisplayChannelClient* dcc,
>                                                                       
>  StreamAgent *agent);
> +void                       dcc_create_stream                        
>  (DisplayChannelClient *dcc,
> +                                                                      Stream
> *stream);
>  
>  typedef struct DrawablePipeItem {
>      RingItem base;  /* link for a list of pipe items held by Drawable */
> diff --git a/server/red_worker.c b/server/red_worker.c
> index 6a331cb..5269752 100644
> --- a/server/red_worker.c
> +++ b/server/red_worker.c
> @@ -80,7 +80,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
> @@ -1353,181 +1352,6 @@ static Stream
> *display_channel_stream_try_new(DisplayChannel *display)
>      return stream;
>  }
>  
> -static uint64_t red_stream_get_initial_bit_rate(DisplayChannelClient *dcc,
> -                                                Stream *stream)
> -{
> -    char *env_bit_rate_str;
> -    uint64_t bit_rate = 0;
> -
> -    env_bit_rate_str = getenv("SPICE_BIT_RATE");
> -    if (env_bit_rate_str != NULL) {
> -        double env_bit_rate;
> -
> -        errno = 0;
> -        env_bit_rate = strtod(env_bit_rate_str, NULL);
> -        if (errno == 0) {
> -            bit_rate = env_bit_rate * 1024 * 1024;
> -        } else {
> -            spice_warning("error parsing SPICE_BIT_RATE: %s",
> strerror(errno));
> -        }
> -    }
> -
> -    if (!bit_rate) {
> -        MainChannelClient *mcc;
> -        uint64_t net_test_bit_rate;
> -
> -        mcc = red_client_get_main(RED_CHANNEL_CLIENT(dcc)->client);
> -        net_test_bit_rate =
> main_channel_client_is_network_info_initialized(mcc) ?
> -                                main_channel_client_get_bitrate_per_sec(mcc)
> :
> -                                0;
> -        bit_rate = MAX(dcc->streams_max_bit_rate, net_test_bit_rate);
> -        if (bit_rate == 0) {
> -            /*
> -             * In case we are after a spice session migration,
> -             * the low_bandwidth flag is retrieved from migration data.
> -             * If the network info is not initialized due to another reason,
> -             * the low_bandwidth flag is FALSE.
> -             */
> -            bit_rate = dcc->common.is_low_bandwidth ?
> -                RED_STREAM_DEFAULT_LOW_START_BIT_RATE :
> -                RED_STREAM_DEFAULT_HIGH_START_BIT_RATE;
> -        }
> -    }
> -
> -    spice_debug("base-bit-rate %.2f (Mbps)", bit_rate / 1024.0 / 1024.0);
> -    /* dividing the available bandwidth among the active streams, and saving
> -     * (1-RED_STREAM_CHANNEL_CAPACITY) of it for other messages */
> -    return (RED_STREAM_CHANNEL_CAPACITY * bit_rate *
> -            stream->width * stream->height) / DCC_TO_DC(dcc)
> ->streams_size_total;
> -}
> -
> -static uint32_t red_stream_mjpeg_encoder_get_roundtrip(void *opaque)
> -{
> -    StreamAgent *agent = opaque;
> -    int roundtrip;
> -
> -    spice_assert(agent);
> -    roundtrip = red_channel_client_get_roundtrip_ms(RED_CHANNEL_CLIENT(agent
> ->dcc));
> -    if (roundtrip < 0) {
> -        MainChannelClient *mcc = red_client_get_main(RED_CHANNEL_CLIENT(agent
> ->dcc)->client);
> -
> -        /*
> -         * the main channel client roundtrip might not have been
> -         * calculated (e.g., after migration). In such case,
> -         * main_channel_client_get_roundtrip_ms returns 0.
> -         */
> -        roundtrip = main_channel_client_get_roundtrip_ms(mcc);
> -    }
> -
> -    return roundtrip;
> -}
> -
> -static uint32_t red_stream_mjpeg_encoder_get_source_fps(void *opaque)
> -{
> -    StreamAgent *agent = opaque;
> -
> -    spice_assert(agent);
> -    return agent->stream->input_fps;
> -}
> -
> -static void red_display_update_streams_max_latency(DisplayChannelClient *dcc,
> StreamAgent *remove_agent)
> -{
> -    uint32_t new_max_latency = 0;
> -    int i;
> -
> -    if (dcc->streams_max_latency != remove_agent->client_required_latency) {
> -        return;
> -    }
> -
> -    dcc->streams_max_latency = 0;
> -    if (DCC_TO_DC(dcc)->stream_count == 1) {
> -        return;
> -    }
> -    for (i = 0; i < NUM_STREAMS; i++) {
> -        StreamAgent *other_agent = &dcc->stream_agents[i];
> -        if (other_agent == remove_agent || !other_agent->mjpeg_encoder) {
> -            continue;
> -        }
> -        if (other_agent->client_required_latency > new_max_latency) {
> -            new_max_latency = other_agent->client_required_latency;
> -        }
> -    }
> -    dcc->streams_max_latency = new_max_latency;
> -}
> -
> -static void red_display_stream_agent_stop(DisplayChannelClient *dcc,
> StreamAgent *agent)
> -{
> -    red_display_update_streams_max_latency(dcc, agent);
> -    if (agent->mjpeg_encoder) {
> -        mjpeg_encoder_destroy(agent->mjpeg_encoder);
> -        agent->mjpeg_encoder = NULL;
> -    }
> -}
> -
> -static void red_stream_update_client_playback_latency(void *opaque, uint32_t
> delay_ms)
> -{
> -    StreamAgent *agent = opaque;
> -    DisplayChannelClient *dcc = agent->dcc;
> -
> -    red_display_update_streams_max_latency(dcc, agent);
> -
> -    agent->client_required_latency = delay_ms;
> -    if (delay_ms > agent->dcc->streams_max_latency) {
> -         agent->dcc->streams_max_latency = delay_ms;
> -    }
> -    spice_debug("resetting client latency: %u", agent->dcc
> ->streams_max_latency);
> -    main_dispatcher_set_mm_time_latency(RED_CHANNEL_CLIENT(agent->dcc)
> ->client, agent->dcc->streams_max_latency);
> -}
> -
> -static void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
> -{
> -    StreamAgent *agent = &dcc->stream_agents[get_stream_id(DCC_TO_DC(dcc),
> stream)];
> -
> -    stream->refs++;
> -    spice_assert(region_is_empty(&agent->vis_region));
> -    if (stream->current) {
> -        agent->frames = 1;
> -        region_clone(&agent->vis_region, &stream->current
> ->tree_item.base.rgn);
> -        region_clone(&agent->clip, &agent->vis_region);
> -    } else {
> -        agent->frames = 0;
> -    }
> -    agent->drops = 0;
> -    agent->fps = MAX_FPS;
> -    agent->dcc = dcc;
> -
> -    if (dcc->use_mjpeg_encoder_rate_control) {
> -        MJpegEncoderRateControlCbs mjpeg_cbs;
> -        uint64_t initial_bit_rate;
> -
> -        mjpeg_cbs.get_roundtrip_ms = red_stream_mjpeg_encoder_get_roundtrip;
> -        mjpeg_cbs.get_source_fps = red_stream_mjpeg_encoder_get_source_fps;
> -        mjpeg_cbs.update_client_playback_delay =
> red_stream_update_client_playback_latency;
> -
> -        initial_bit_rate = red_stream_get_initial_bit_rate(dcc, stream);
> -        agent->mjpeg_encoder = mjpeg_encoder_new(initial_bit_rate,
> &mjpeg_cbs, agent);
> -    } else {
> -        agent->mjpeg_encoder = mjpeg_encoder_new(0, NULL, NULL);
> -    }
> -    red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &agent
> ->create_item);
> -
> -    if (red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(dcc),
> SPICE_DISPLAY_CAP_STREAM_REPORT)) {
> -        StreamActivateReportItem *report_pipe_item =
> spice_malloc0(sizeof(*report_pipe_item));
> -
> -        agent->report_id = rand();
> -        red_channel_pipe_item_init(RED_CHANNEL_CLIENT(dcc)->channel,
> &report_pipe_item->pipe_item,
> -                                   PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT);
> -        report_pipe_item->stream_id = get_stream_id(DCC_TO_DC(dcc), stream);
> -        red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc),
> &report_pipe_item->pipe_item);
> -    }
> -#ifdef STREAM_STATS
> -    memset(&agent->stats, 0, sizeof(StreamStats));
> -    if (stream->current) {
> -        agent->stats.start = stream->current->red_drawable->mm_time;
> -    }
> -#endif
> -}
> -
>  static void display_channel_create_stream(DisplayChannel *display, Drawable
> *drawable)
>  {
>      DisplayChannelClient *dcc;
> @@ -6872,7 +6696,7 @@ 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_TO_DC(dcc), agent->stream);
> -    red_display_stream_agent_stop(dcc, agent);
> +    stream_agent_stop(dcc, agent);
>      spice_marshall_msg_display_stream_destroy(base_marshaller, &destroy);
>  }
>  
> diff --git a/server/stream.c b/server/stream.c
> index 406111c..27d6d36 100644
> --- a/server/stream.c
> +++ b/server/stream.c
> @@ -138,3 +138,177 @@ StreamClipItem
> *stream_clip_item_new(DisplayChannelClient* dcc, StreamAgent *age
>      item->refs = 1;
>      return item;
>  }
> +
> +static void dcc_update_streams_max_latency(DisplayChannelClient *dcc,
> StreamAgent *remove_agent)
> +{
> +    uint32_t new_max_latency = 0;
> +    int i;
> +
> +    if (dcc->streams_max_latency != remove_agent->client_required_latency) {
> +        return;
> +    }
> +
> +    dcc->streams_max_latency = 0;
> +    if (DCC_TO_DC(dcc)->stream_count == 1) {
> +        return;
> +    }
> +    for (i = 0; i < NUM_STREAMS; i++) {
> +        StreamAgent *other_agent = &dcc->stream_agents[i];
> +        if (other_agent == remove_agent || !other_agent->mjpeg_encoder) {
> +            continue;
> +        }
> +        if (other_agent->client_required_latency > new_max_latency) {
> +            new_max_latency = other_agent->client_required_latency;
> +        }
> +    }
> +    dcc->streams_max_latency = new_max_latency;
> +}
> +
> +static uint64_t red_stream_get_initial_bit_rate(DisplayChannelClient *dcc,
> +                                                Stream *stream)
> +{
> +    char *env_bit_rate_str;
> +    uint64_t bit_rate = 0;
> +
> +    env_bit_rate_str = getenv("SPICE_BIT_RATE");
> +    if (env_bit_rate_str != NULL) {
> +        double env_bit_rate;
> +
> +        errno = 0;
> +        env_bit_rate = strtod(env_bit_rate_str, NULL);
> +        if (errno == 0) {
> +            bit_rate = env_bit_rate * 1024 * 1024;
> +        } else {
> +            spice_warning("error parsing SPICE_BIT_RATE: %s",
> strerror(errno));
> +        }
> +    }
> +
> +    if (!bit_rate) {
> +        MainChannelClient *mcc;
> +        uint64_t net_test_bit_rate;
> +
> +        mcc = red_client_get_main(RED_CHANNEL_CLIENT(dcc)->client);
> +        net_test_bit_rate =
> main_channel_client_is_network_info_initialized(mcc) ?
> +                                main_channel_client_get_bitrate_per_sec(mcc)
> :
> +                                0;
> +        bit_rate = MAX(dcc->streams_max_bit_rate, net_test_bit_rate);
> +        if (bit_rate == 0) {
> +            /*
> +             * In case we are after a spice session migration,
> +             * the low_bandwidth flag is retrieved from migration data.
> +             * If the network info is not initialized due to another reason,
> +             * the low_bandwidth flag is FALSE.
> +             */
> +            bit_rate = dcc->common.is_low_bandwidth ?
> +                RED_STREAM_DEFAULT_LOW_START_BIT_RATE :
> +                RED_STREAM_DEFAULT_HIGH_START_BIT_RATE;
> +        }
> +    }
> +
> +    spice_debug("base-bit-rate %.2f (Mbps)", bit_rate / 1024.0 / 1024.0);
> +    /* dividing the available bandwidth among the active streams, and saving
> +     * (1-RED_STREAM_CHANNEL_CAPACITY) of it for other messages */
> +    return (RED_STREAM_CHANNEL_CAPACITY * bit_rate *
> +            stream->width * stream->height) / DCC_TO_DC(dcc)
> ->streams_size_total;
> +}
> +
> +static uint32_t red_stream_mjpeg_encoder_get_roundtrip(void *opaque)
> +{
> +    StreamAgent *agent = opaque;
> +    int roundtrip;
> +
> +    roundtrip = red_channel_client_get_roundtrip_ms(RED_CHANNEL_CLIENT(agent
> ->dcc));
> +    if (roundtrip < 0) {
> +        MainChannelClient *mcc = red_client_get_main(RED_CHANNEL_CLIENT(agent
> ->dcc)->client);
> +
> +        /*
> +         * the main channel client roundtrip might not have been
> +         * calculated (e.g., after migration). In such case,
> +         * main_channel_client_get_roundtrip_ms returns 0.
> +         */
> +        roundtrip = main_channel_client_get_roundtrip_ms(mcc);
> +    }
> +
> +    return roundtrip;
> +}
> +
> +static uint32_t red_stream_mjpeg_encoder_get_source_fps(void *opaque)
> +{
> +    StreamAgent *agent = opaque;
> +
> +    return agent->stream->input_fps;
> +}
> +
> +static void red_stream_update_client_playback_latency(void *opaque, uint32_t
> delay_ms)
> +{
> +    StreamAgent *agent = opaque;
> +    DisplayChannelClient *dcc = agent->dcc;
> +
> +    dcc_update_streams_max_latency(dcc, agent);
> +
> +    agent->client_required_latency = delay_ms;
> +    if (delay_ms > agent->dcc->streams_max_latency) {
> +        agent->dcc->streams_max_latency = delay_ms;
> +    }
> +    spice_debug("resetting client latency: %u", agent->dcc
> ->streams_max_latency);
> +    main_dispatcher_set_mm_time_latency(RED_CHANNEL_CLIENT(agent->dcc)
> ->client, agent->dcc->streams_max_latency);
> +}
> +
> +void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
> +{
> +    StreamAgent *agent = &dcc->stream_agents[get_stream_id(DCC_TO_DC(dcc),
> stream)];
> +
> +    spice_return_if_fail(region_is_empty(&agent->vis_region));
> +
> +    stream->refs++;
> +    if (stream->current) {
> +        agent->frames = 1;
> +        region_clone(&agent->vis_region, &stream->current
> ->tree_item.base.rgn);
> +        region_clone(&agent->clip, &agent->vis_region);
> +    } else {
> +        agent->frames = 0;
> +    }
> +    agent->drops = 0;
> +    agent->fps = MAX_FPS;
> +    agent->dcc = dcc;
> +
> +    if (dcc->use_mjpeg_encoder_rate_control) {
> +        MJpegEncoderRateControlCbs mjpeg_cbs;
> +        uint64_t initial_bit_rate;
> +
> +        mjpeg_cbs.get_roundtrip_ms = red_stream_mjpeg_encoder_get_roundtrip;
> +        mjpeg_cbs.get_source_fps = red_stream_mjpeg_encoder_get_source_fps;
> +        mjpeg_cbs.update_client_playback_delay =
> red_stream_update_client_playback_latency;
> +
> +        initial_bit_rate = red_stream_get_initial_bit_rate(dcc, stream);
> +        agent->mjpeg_encoder = mjpeg_encoder_new(initial_bit_rate,
> &mjpeg_cbs, agent);
> +    } else {
> +        agent->mjpeg_encoder = mjpeg_encoder_new(0, NULL, NULL);
> +    }
> +    red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &agent
> ->create_item);
> +
> +    if (red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(dcc),
> SPICE_DISPLAY_CAP_STREAM_REPORT)) {
> +        StreamActivateReportItem *report_pipe_item =
> spice_malloc0(sizeof(*report_pipe_item));
> +
> +        agent->report_id = rand();
> +        red_channel_pipe_item_init(RED_CHANNEL_CLIENT(dcc)->channel,
> &report_pipe_item->pipe_item,
> +                                   PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT);
> +        report_pipe_item->stream_id = get_stream_id(DCC_TO_DC(dcc), stream);
> +        red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc),
> &report_pipe_item->pipe_item);
> +    }
> +#ifdef STREAM_STATS
> +    memset(&agent->stats, 0, sizeof(StreamStats));
> +    if (stream->current) {
> +        agent->stats.start = stream->current->red_drawable->mm_time;
> +    }
> +#endif
> +}
> +
> +void stream_agent_stop(DisplayChannelClient *dcc, StreamAgent *agent)
> +{
> +    dcc_update_streams_max_latency(dcc, agent);
> +    if (agent->mjpeg_encoder) {
> +        mjpeg_encoder_destroy(agent->mjpeg_encoder);
> +        agent->mjpeg_encoder = NULL;
> +    }
> +}
> diff --git a/server/stream.h b/server/stream.h
> index 09df31b..c2007af 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,7 @@ void                  stream_unref                        
>           (DisplayChan
>  void                  stream_agent_unref                           
>  (DisplayChannel *display,
>                                                                      
>  StreamAgent *agent);
>  void                  stream_agent_stats_print                     
>  (StreamAgent *agent);
> +void                  stream_agent_stop                            
>  (DisplayChannelClient *dcc,
> +                                                                    
>  StreamAgent *agent);
>  
>  #endif /* STREAM_H */


More information about the Spice-devel mailing list