The declaration is already in dcc.h. Also move helper functions. Signed-off-by: Jonathon Jongsma <jjongsma@xxxxxxxxxx> --- server/dcc.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ server/stream.c | 186 -------------------------------------------------------- 2 files changed, 186 insertions(+), 186 deletions(-) diff --git a/server/dcc.c b/server/dcc.c index 6e64f44d3..00bc28b92 100644 --- a/server/dcc.c +++ b/server/dcc.c @@ -1546,3 +1546,189 @@ RedPipeItem *stream_destroy_item_new(StreamAgent *agent) return stream_create_destroy_item_new(agent, RED_PIPE_ITEM_TYPE_STREAM_DESTROY); } +static uint64_t 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_get_client(RED_CHANNEL_CLIENT(dcc))); + 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_get_max_stream_bit_rate(dcc), 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_is_low_bandwidth(dcc) ? + 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)->priv->streams_size_total; +} + +static uint32_t get_roundtrip_ms(void *opaque) +{ + StreamAgent *agent = opaque; + int roundtrip; + RedChannelClient *rcc = RED_CHANNEL_CLIENT(agent->dcc); + + roundtrip = red_channel_client_get_roundtrip_ms(rcc); + if (roundtrip < 0) { + MainChannelClient *mcc = red_client_get_main(red_channel_client_get_client(rcc)); + + /* + * 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 get_source_fps(void *opaque) +{ + StreamAgent *agent = opaque; + + return agent->stream->input_fps; +} + +static void update_client_playback_delay(void *opaque, uint32_t delay_ms) +{ + StreamAgent *agent = opaque; + DisplayChannelClient *dcc = agent->dcc; + RedChannel *channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(dcc)); + RedClient *client = red_channel_client_get_client(RED_CHANNEL_CLIENT(dcc)); + RedsState *reds = red_channel_get_server(channel); + + dcc_update_streams_max_latency(dcc, agent); + + agent->client_required_latency = delay_ms; + if (delay_ms > dcc_get_max_stream_latency(dcc)) { + dcc_set_max_stream_latency(dcc, delay_ms); + } + spice_debug("resetting client latency: %u", dcc_get_max_stream_latency(dcc)); + main_dispatcher_set_mm_time_latency(reds_get_main_dispatcher(reds), + client, + dcc_get_max_stream_latency(agent->dcc)); +} + +static void bitmap_ref(gpointer data) +{ + RedDrawable *red_drawable = (RedDrawable*)data; + red_drawable_ref(red_drawable); +} + +static void bitmap_unref(gpointer data) +{ + RedDrawable *red_drawable = (RedDrawable*)data; + red_drawable_unref(red_drawable); +} + +/* A helper for dcc_create_stream(). */ +static VideoEncoder* dcc_create_video_encoder(DisplayChannelClient *dcc, + uint64_t starting_bit_rate, + VideoEncoderRateControlCbs *cbs) +{ + RedChannelClient *rcc = RED_CHANNEL_CLIENT(dcc); + bool client_has_multi_codec = red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_MULTI_CODEC); + int i; + GArray *video_codecs; + + video_codecs = dcc_get_preferred_video_codecs_for_encoding(dcc); + for (i = 0; i < video_codecs->len; i++) { + RedVideoCodec* video_codec = &g_array_index (video_codecs, RedVideoCodec, i); + + if (!client_has_multi_codec && + video_codec->type != SPICE_VIDEO_CODEC_TYPE_MJPEG) { + /* Old clients only support MJPEG */ + continue; + } + if (client_has_multi_codec && + !red_channel_client_test_remote_cap(rcc, video_codec->cap)) { + /* The client is recent but does not support this codec */ + continue; + } + + VideoEncoder* video_encoder = video_codec->create(video_codec->type, starting_bit_rate, cbs, bitmap_ref, bitmap_unref); + if (video_encoder) { + return video_encoder; + } + } + + /* Try to use the builtin MJPEG video encoder as a fallback */ + if (!client_has_multi_codec || red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_CODEC_MJPEG)) { + return mjpeg_encoder_new(SPICE_VIDEO_CODEC_TYPE_MJPEG, starting_bit_rate, cbs, bitmap_ref, bitmap_unref); + } + + return NULL; +} + +void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream) +{ + StreamAgent *agent = dcc_get_stream_agent(dcc, display_channel_get_stream_id(DCC_TO_DC(dcc), stream)); + + spice_return_if_fail(region_is_empty(&agent->vis_region)); + + if (stream->current) { + region_clone(&agent->vis_region, &stream->current->tree_item.base.rgn); + region_clone(&agent->clip, &agent->vis_region); + } + agent->fps = MAX_FPS; + agent->dcc = dcc; + + VideoEncoderRateControlCbs video_cbs; + video_cbs.opaque = agent; + video_cbs.get_roundtrip_ms = get_roundtrip_ms; + video_cbs.get_source_fps = get_source_fps; + video_cbs.update_client_playback_delay = update_client_playback_delay; + + uint64_t initial_bit_rate = get_initial_bit_rate(dcc, stream); + agent->video_encoder = dcc_create_video_encoder(dcc, initial_bit_rate, &video_cbs); + red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), stream_create_item_new(agent)); + + if (red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(dcc), SPICE_DISPLAY_CAP_STREAM_REPORT)) { + RedStreamActivateReportItem *report_pipe_item = g_new0(RedStreamActivateReportItem, 1); + + agent->report_id = rand(); + red_pipe_item_init(&report_pipe_item->pipe_item, + RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT); + report_pipe_item->stream_id = display_channel_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 +} + diff --git a/server/stream.c b/server/stream.c index 6b585f653..f45a92feb 100644 --- a/server/stream.c +++ b/server/stream.c @@ -499,192 +499,6 @@ void stream_maintenance(DisplayChannel *display, } } -static uint64_t 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_get_client(RED_CHANNEL_CLIENT(dcc))); - 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_get_max_stream_bit_rate(dcc), 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_is_low_bandwidth(dcc) ? - 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)->priv->streams_size_total; -} - -static uint32_t get_roundtrip_ms(void *opaque) -{ - StreamAgent *agent = opaque; - int roundtrip; - RedChannelClient *rcc = RED_CHANNEL_CLIENT(agent->dcc); - - roundtrip = red_channel_client_get_roundtrip_ms(rcc); - if (roundtrip < 0) { - MainChannelClient *mcc = red_client_get_main(red_channel_client_get_client(rcc)); - - /* - * 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 get_source_fps(void *opaque) -{ - StreamAgent *agent = opaque; - - return agent->stream->input_fps; -} - -static void update_client_playback_delay(void *opaque, uint32_t delay_ms) -{ - StreamAgent *agent = opaque; - DisplayChannelClient *dcc = agent->dcc; - RedChannel *channel = red_channel_client_get_channel(RED_CHANNEL_CLIENT(dcc)); - RedClient *client = red_channel_client_get_client(RED_CHANNEL_CLIENT(dcc)); - RedsState *reds = red_channel_get_server(channel); - - dcc_update_streams_max_latency(dcc, agent); - - agent->client_required_latency = delay_ms; - if (delay_ms > dcc_get_max_stream_latency(dcc)) { - dcc_set_max_stream_latency(dcc, delay_ms); - } - spice_debug("resetting client latency: %u", dcc_get_max_stream_latency(dcc)); - main_dispatcher_set_mm_time_latency(reds_get_main_dispatcher(reds), - client, - dcc_get_max_stream_latency(agent->dcc)); -} - -static void bitmap_ref(gpointer data) -{ - RedDrawable *red_drawable = (RedDrawable*)data; - red_drawable_ref(red_drawable); -} - -static void bitmap_unref(gpointer data) -{ - RedDrawable *red_drawable = (RedDrawable*)data; - red_drawable_unref(red_drawable); -} - -/* A helper for dcc_create_stream(). */ -static VideoEncoder* dcc_create_video_encoder(DisplayChannelClient *dcc, - uint64_t starting_bit_rate, - VideoEncoderRateControlCbs *cbs) -{ - RedChannelClient *rcc = RED_CHANNEL_CLIENT(dcc); - bool client_has_multi_codec = red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_MULTI_CODEC); - int i; - GArray *video_codecs; - - video_codecs = dcc_get_preferred_video_codecs_for_encoding(dcc); - for (i = 0; i < video_codecs->len; i++) { - RedVideoCodec* video_codec = &g_array_index (video_codecs, RedVideoCodec, i); - - if (!client_has_multi_codec && - video_codec->type != SPICE_VIDEO_CODEC_TYPE_MJPEG) { - /* Old clients only support MJPEG */ - continue; - } - if (client_has_multi_codec && - !red_channel_client_test_remote_cap(rcc, video_codec->cap)) { - /* The client is recent but does not support this codec */ - continue; - } - - VideoEncoder* video_encoder = video_codec->create(video_codec->type, starting_bit_rate, cbs, bitmap_ref, bitmap_unref); - if (video_encoder) { - return video_encoder; - } - } - - /* Try to use the builtin MJPEG video encoder as a fallback */ - if (!client_has_multi_codec || red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_CODEC_MJPEG)) { - return mjpeg_encoder_new(SPICE_VIDEO_CODEC_TYPE_MJPEG, starting_bit_rate, cbs, bitmap_ref, bitmap_unref); - } - - return NULL; -} - -void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream) -{ - StreamAgent *agent = dcc_get_stream_agent(dcc, display_channel_get_stream_id(DCC_TO_DC(dcc), stream)); - - spice_return_if_fail(region_is_empty(&agent->vis_region)); - - if (stream->current) { - region_clone(&agent->vis_region, &stream->current->tree_item.base.rgn); - region_clone(&agent->clip, &agent->vis_region); - } - agent->fps = MAX_FPS; - agent->dcc = dcc; - - VideoEncoderRateControlCbs video_cbs; - video_cbs.opaque = agent; - video_cbs.get_roundtrip_ms = get_roundtrip_ms; - video_cbs.get_source_fps = get_source_fps; - video_cbs.update_client_playback_delay = update_client_playback_delay; - - uint64_t initial_bit_rate = get_initial_bit_rate(dcc, stream); - agent->video_encoder = dcc_create_video_encoder(dcc, initial_bit_rate, &video_cbs); - red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), stream_create_item_new(agent)); - - if (red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(dcc), SPICE_DISPLAY_CAP_STREAM_REPORT)) { - RedStreamActivateReportItem *report_pipe_item = g_new0(RedStreamActivateReportItem, 1); - - agent->report_id = rand(); - red_pipe_item_init(&report_pipe_item->pipe_item, - RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT); - report_pipe_item->stream_id = display_channel_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(StreamAgent *agent) { DisplayChannelClient *dcc = agent->dcc; -- 2.13.6 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel