[Spice-devel] [PATCH spice-server 3/7] Move stream creation/maintenance funcs to DisplayChannel
Jonathon Jongsma
jjongsma at redhat.com
Wed Nov 29 20:16:06 UTC 2017
These functions were really DisplayChannel methods but were mixed in
with the VideoStream (and some DisplayChannelClient code) in
video-stream.h. Putting it in the proper location helps organize the
code better and allows us to make several functions static.
Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
---
server/display-channel.c | 383 +++++++++++++++++++++++++++++++++++++++++++++++
server/video-stream.c | 378 ----------------------------------------------
server/video-stream.h | 4 -
3 files changed, 383 insertions(+), 382 deletions(-)
diff --git a/server/display-channel.c b/server/display-channel.c
index d3db1e0db..96feabc3c 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -25,6 +25,10 @@
G_DEFINE_TYPE(DisplayChannel, display_channel, TYPE_COMMON_GRAPHICS_CHANNEL)
+static void video_stream_maintenance(DisplayChannel *display,
+ Drawable *candidate,
+ Drawable *prev);
+static void video_stream_trace_update(DisplayChannel *display, Drawable *drawable);
enum {
PROP0,
PROP_N_SURFACES,
@@ -424,6 +428,26 @@ static void current_add_drawable(DisplayChannel *display,
drawable->refs++;
}
+static void video_stream_trace_add_drawable(DisplayChannel *display,
+ Drawable *item)
+{
+ ItemTrace *trace;
+
+ if (item->stream || !item->streamable) {
+ return;
+ }
+
+ trace = &display->priv->items_trace[display->priv->next_item_trace++ & ITEMS_TRACE_MASK];
+ trace->time = item->creation_time;
+ trace->first_frame_time = item->first_frame_time;
+ trace->frames_count = item->frames_count;
+ trace->gradual_frames_count = item->gradual_frames_count;
+ trace->last_gradual_frame = item->last_gradual_frame;
+ SpiceRect* src_area = &item->red_drawable->u.copy.src_area;
+ trace->width = src_area->right - src_area->left;
+ trace->height = src_area->bottom - src_area->top;
+ trace->dest_area = item->red_drawable->bbox;
+}
/* Unrefs the drawable and removes it from any rings that it's in, as well as
* removing any associated shadow item */
static void current_remove_drawable(DisplayChannel *display, Drawable *item)
@@ -2566,3 +2590,362 @@ void display_channel_debug_oom(DisplayChannel *display, const char *msg)
ring_get_length(&display->priv->current_list),
red_channel_sum_pipes_size(channel));
}
+
+static bool 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 VideoStream *stream,
+ int container_candidate_allowed)
+{
+ RedDrawable *red_drawable;
+
+ if (!candidate->streamable) {
+ return FALSE;
+ }
+
+ if (candidate->creation_time - other_time >
+ (stream ? RED_STREAM_CONTINUOUS_MAX_DELTA : RED_STREAM_DETECTION_MAX_DELTA)) {
+ return FALSE;
+ }
+
+ red_drawable = candidate->red_drawable;
+ if (!container_candidate_allowed) {
+ SpiceRect* candidate_src;
+
+ if (!rect_is_equal(&red_drawable->bbox, other_dest)) {
+ return FALSE;
+ }
+
+ 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 FALSE;
+ }
+ } else {
+ if (!rect_contains(&red_drawable->bbox, other_dest)) {
+ return FALSE;
+ }
+ 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 FALSE;
+ }
+ }
+
+ if (stream) {
+ SpiceBitmap *bitmap = &red_drawable->u.copy.src_bitmap->u.bitmap;
+ if (stream->top_down != !!(bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static void before_reattach_stream(DisplayChannel *display,
+ VideoStream *stream, Drawable *new_frame)
+{
+ DisplayChannelClient *dcc;
+ int index;
+ VideoStreamAgent *agent;
+ GList *dpi_link, *dpi_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 = display_channel_get_video_stream_id(display, stream);
+ for (dpi_link = stream->current->pipes; dpi_link; dpi_link = dpi_next) {
+ RedDrawablePipeItem *dpi = dpi_link->data;
+ dpi_next = dpi_link->next;
+ dcc = dpi->dcc;
+ agent = dcc_get_video_stream_agent(dcc, index);
+
+ if (red_channel_client_pipe_item_is_linked(RED_CHANNEL_CLIENT(dcc),
+ &dpi->dpi_pipe_item)) {
+#ifdef STREAM_STATS
+ agent->stats.num_drops_pipe++;
+#endif
+ agent->video_encoder->notify_server_frame_drop(agent->video_encoder);
+ }
+ }
+}
+
+
+static void attach_stream(DisplayChannel *display, Drawable *drawable, VideoStream *stream)
+{
+ DisplayChannelClient *dcc;
+
+ spice_assert(drawable && stream);
+ spice_assert(!drawable->stream && !stream->current);
+ stream->current = drawable;
+ drawable->stream = stream;
+ stream->last_time = drawable->creation_time;
+
+ uint64_t duration = drawable->creation_time - stream->input_fps_start_time;
+ if (duration >= RED_STREAM_INPUT_FPS_TIMEOUT) {
+ /* Round to the nearest integer, for instance 24 for 23.976 */
+ stream->input_fps = ((uint64_t)stream->num_input_frames * 1000 * 1000 * 1000 + duration / 2) / duration;
+ spice_debug("input-fps=%u", stream->input_fps);
+ stream->num_input_frames = 0;
+ stream->input_fps_start_time = drawable->creation_time;
+ } else {
+ stream->num_input_frames++;
+ }
+
+ FOREACH_DCC(display, dcc) {
+ VideoStreamAgent *agent;
+ QRegion clip_in_draw_dest;
+ int stream_id = display_channel_get_video_stream_id(display, stream);
+
+ agent = dcc_get_video_stream_agent(dcc, stream_id);
+ region_or(&agent->vis_region, &drawable->tree_item.base.rgn);
+
+ region_init(&clip_in_draw_dest);
+ region_add(&clip_in_draw_dest, &drawable->red_drawable->bbox);
+ region_and(&clip_in_draw_dest, &agent->clip);
+
+ if (!region_is_equal(&clip_in_draw_dest, &drawable->tree_item.base.rgn)) {
+ region_remove(&agent->clip, &drawable->red_drawable->bbox);
+ region_or(&agent->clip, &drawable->tree_item.base.rgn);
+ dcc_video_stream_agent_clip(dcc, agent);
+ }
+ region_destroy(&clip_in_draw_dest);
+#ifdef STREAM_STATS
+ agent->stats.num_input_frames++;
+#endif
+ }
+}
+
+static void update_copy_graduality(DisplayChannel *display, Drawable *drawable)
+{
+ SpiceBitmap *bitmap;
+ spice_return_if_fail(drawable->red_drawable->type == QXL_DRAW_COPY);
+
+ if (display_channel_get_stream_video(display) != 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)));
+}
+
+static VideoStream *display_channel_stream_try_new(DisplayChannel *display)
+{
+ VideoStream *stream;
+ if (!display->priv->free_streams) {
+ return NULL;
+ }
+ stream = display->priv->free_streams;
+ display->priv->free_streams = display->priv->free_streams->next;
+ stream->display = display;
+ return stream;
+}
+
+static void display_channel_create_stream(DisplayChannel *display, Drawable *drawable)
+{
+ DisplayChannelClient *dcc;
+ VideoStream *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->priv->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;
+ /* Provide an fps estimate the video encoder can use when initializing
+ * based on the frames that lead to the creation of the stream. Round to
+ * the nearest integer, for instance 24 for 23.976.
+ */
+ uint64_t duration = drawable->creation_time - drawable->first_frame_time;
+ if (duration > NSEC_PER_SEC * drawable->frames_count / MAX_FPS) {
+ stream->input_fps = (NSEC_PER_SEC * drawable->frames_count + duration / 2) / duration;
+ } else {
+ stream->input_fps = MAX_FPS;
+ }
+ stream->num_input_frames = 0;
+ stream->input_fps_start_time = drawable->creation_time;
+ display->priv->streams_size_total += stream->width * stream->height;
+ display->priv->stream_count++;
+ FOREACH_DCC(display, dcc) {
+ dcc_create_stream(dcc, stream);
+ }
+ spice_debug("stream %d %dx%d (%d, %d) (%d, %d) %u fps",
+ display_channel_get_video_stream_id(display, stream), stream->width,
+ stream->height, stream->dest_area.left, stream->dest_area.top,
+ stream->dest_area.right, stream->dest_area.bottom,
+ stream->input_fps);
+}
+
+// returns whether a stream was created
+static bool video_stream_add_frame(DisplayChannel *display,
+ Drawable *frame_drawable,
+ red_time_t first_frame_time,
+ int frames_count,
+ int gradual_frames_count,
+ int last_gradual_frame)
+{
+ update_copy_graduality(display, frame_drawable);
+ frame_drawable->first_frame_time = first_frame_time;
+ 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 video_stream_trace_update(DisplayChannel *display, Drawable *drawable)
+{
+ ItemTrace *trace;
+ ItemTrace *trace_end;
+ RingItem *item;
+
+ if (drawable->stream || !drawable->streamable || drawable->frames_count) {
+ return;
+ }
+
+ RING_FOREACH(item, &(display)->priv->streams) {
+ VideoStream *stream = SPICE_CONTAINEROF(item, VideoStream, link);
+ bool 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) {
+ if (stream->current) {
+ stream->current->streamable = FALSE; //prevent item trace
+ before_reattach_stream(display, stream, drawable);
+ video_stream_detach_drawable(stream);
+ }
+ attach_stream(display, drawable, stream);
+ return;
+ }
+ }
+
+ trace = display->priv->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)) {
+ if (video_stream_add_frame(display, drawable,
+ trace->first_frame_time,
+ trace->frames_count,
+ trace->gradual_frames_count,
+ trace->last_gradual_frame)) {
+ return;
+ }
+ }
+ }
+}
+
+void video_stream_maintenance(DisplayChannel *display,
+ Drawable *candidate, Drawable *prev)
+{
+ bool is_next_frame;
+
+ if (candidate->stream) {
+ return;
+ }
+
+ if (prev->stream) {
+ VideoStream *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) {
+ before_reattach_stream(display, stream, candidate);
+ video_stream_detach_drawable(stream);
+ prev->streamable = FALSE; //prevent item trace
+ attach_stream(display, candidate, 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) {
+ video_stream_add_frame(display, candidate,
+ prev->first_frame_time,
+ prev->frames_count,
+ prev->gradual_frames_count,
+ prev->last_gradual_frame);
+ }
+ }
+}
+
+
diff --git a/server/video-stream.c b/server/video-stream.c
index a24c787ef..ddb76a679 100644
--- a/server/video-stream.c
+++ b/server/video-stream.c
@@ -24,8 +24,6 @@
#include "red-client.h"
#define FPS_TEST_INTERVAL 1
-#define FOREACH_STREAMS(display, item) \
- RING_FOREACH(item, &(display)->priv->streams)
static void video_stream_agent_stats_print(VideoStreamAgent *agent)
{
@@ -166,142 +164,6 @@ VideoStreamClipItem *video_stream_clip_item_new(VideoStreamAgent *agent)
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_channel_get_stream_video(display) != 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 bool 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 VideoStream *stream,
- int container_candidate_allowed)
-{
- RedDrawable *red_drawable;
-
- if (!candidate->streamable) {
- return FALSE;
- }
-
- if (candidate->creation_time - other_time >
- (stream ? RED_STREAM_CONTINUOUS_MAX_DELTA : RED_STREAM_DETECTION_MAX_DELTA)) {
- return FALSE;
- }
-
- red_drawable = candidate->red_drawable;
- if (!container_candidate_allowed) {
- SpiceRect* candidate_src;
-
- if (!rect_is_equal(&red_drawable->bbox, other_dest)) {
- return FALSE;
- }
-
- 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 FALSE;
- }
- } else {
- if (!rect_contains(&red_drawable->bbox, other_dest)) {
- return FALSE;
- }
- 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 FALSE;
- }
- }
-
- if (stream) {
- SpiceBitmap *bitmap = &red_drawable->u.copy.src_bitmap->u.bitmap;
- if (stream->top_down != !!(bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) {
- return FALSE;
- }
- }
- return TRUE;
-}
-
-static void attach_stream(DisplayChannel *display, Drawable *drawable, VideoStream *stream)
-{
- DisplayChannelClient *dcc;
-
- spice_assert(drawable && stream);
- spice_assert(!drawable->stream && !stream->current);
- stream->current = drawable;
- drawable->stream = stream;
- stream->last_time = drawable->creation_time;
-
- uint64_t duration = drawable->creation_time - stream->input_fps_start_time;
- if (duration >= RED_STREAM_INPUT_FPS_TIMEOUT) {
- /* Round to the nearest integer, for instance 24 for 23.976 */
- stream->input_fps = ((uint64_t)stream->num_input_frames * 1000 * 1000 * 1000 + duration / 2) / duration;
- spice_debug("input-fps=%u", stream->input_fps);
- stream->num_input_frames = 0;
- stream->input_fps_start_time = drawable->creation_time;
- } else {
- stream->num_input_frames++;
- }
-
- FOREACH_DCC(display, dcc) {
- VideoStreamAgent *agent;
- QRegion clip_in_draw_dest;
- int stream_id = display_channel_get_video_stream_id(display, stream);
-
- agent = dcc_get_video_stream_agent(dcc, stream_id);
- region_or(&agent->vis_region, &drawable->tree_item.base.rgn);
-
- region_init(&clip_in_draw_dest);
- region_add(&clip_in_draw_dest, &drawable->red_drawable->bbox);
- region_and(&clip_in_draw_dest, &agent->clip);
-
- if (!region_is_equal(&clip_in_draw_dest, &drawable->tree_item.base.rgn)) {
- region_remove(&agent->clip, &drawable->red_drawable->bbox);
- region_or(&agent->clip, &drawable->tree_item.base.rgn);
- dcc_video_stream_agent_clip(dcc, agent);
- }
- region_destroy(&clip_in_draw_dest);
-#ifdef STREAM_STATS
- agent->stats.num_input_frames++;
-#endif
- }
-}
-
void video_stream_detach_drawable(VideoStream *stream)
{
spice_assert(stream->current && stream->current->stream);
@@ -310,226 +172,6 @@ void video_stream_detach_drawable(VideoStream *stream)
stream->current = NULL;
}
-static void before_reattach_stream(DisplayChannel *display,
- VideoStream *stream, Drawable *new_frame)
-{
- DisplayChannelClient *dcc;
- int index;
- VideoStreamAgent *agent;
- GList *dpi_link, *dpi_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 = display_channel_get_video_stream_id(display, stream);
- for (dpi_link = stream->current->pipes; dpi_link; dpi_link = dpi_next) {
- RedDrawablePipeItem *dpi = dpi_link->data;
- dpi_next = dpi_link->next;
- dcc = dpi->dcc;
- agent = dcc_get_video_stream_agent(dcc, index);
-
- if (red_channel_client_pipe_item_is_linked(RED_CHANNEL_CLIENT(dcc),
- &dpi->dpi_pipe_item)) {
-#ifdef STREAM_STATS
- agent->stats.num_drops_pipe++;
-#endif
- agent->video_encoder->notify_server_frame_drop(agent->video_encoder);
- }
- }
-}
-
-static VideoStream *display_channel_stream_try_new(DisplayChannel *display)
-{
- VideoStream *stream;
- if (!display->priv->free_streams) {
- return NULL;
- }
- stream = display->priv->free_streams;
- display->priv->free_streams = display->priv->free_streams->next;
- stream->display = display;
- return stream;
-}
-
-static void display_channel_create_stream(DisplayChannel *display, Drawable *drawable)
-{
- DisplayChannelClient *dcc;
- VideoStream *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->priv->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;
- /* Provide an fps estimate the video encoder can use when initializing
- * based on the frames that lead to the creation of the stream. Round to
- * the nearest integer, for instance 24 for 23.976.
- */
- uint64_t duration = drawable->creation_time - drawable->first_frame_time;
- if (duration > NSEC_PER_SEC * drawable->frames_count / MAX_FPS) {
- stream->input_fps = (NSEC_PER_SEC * drawable->frames_count + duration / 2) / duration;
- } else {
- stream->input_fps = MAX_FPS;
- }
- stream->num_input_frames = 0;
- stream->input_fps_start_time = drawable->creation_time;
- display->priv->streams_size_total += stream->width * stream->height;
- display->priv->stream_count++;
- FOREACH_DCC(display, dcc) {
- dcc_create_stream(dcc, stream);
- }
- spice_debug("stream %d %dx%d (%d, %d) (%d, %d) %u fps",
- display_channel_get_video_stream_id(display, stream), stream->width,
- stream->height, stream->dest_area.left, stream->dest_area.top,
- stream->dest_area.right, stream->dest_area.bottom,
- stream->input_fps);
-}
-
-// returns whether a stream was created
-static bool video_stream_add_frame(DisplayChannel *display,
- Drawable *frame_drawable,
- red_time_t first_frame_time,
- int frames_count,
- int gradual_frames_count,
- int last_gradual_frame)
-{
- update_copy_graduality(display, frame_drawable);
- frame_drawable->first_frame_time = first_frame_time;
- 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 video_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) {
- VideoStream *stream = SPICE_CONTAINEROF(item, VideoStream, link);
- bool 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) {
- if (stream->current) {
- stream->current->streamable = FALSE; //prevent item trace
- before_reattach_stream(display, stream, drawable);
- video_stream_detach_drawable(stream);
- }
- attach_stream(display, drawable, stream);
- return;
- }
- }
-
- trace = display->priv->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)) {
- if (video_stream_add_frame(display, drawable,
- trace->first_frame_time,
- trace->frames_count,
- trace->gradual_frames_count,
- trace->last_gradual_frame)) {
- return;
- }
- }
- }
-}
-
-void video_stream_maintenance(DisplayChannel *display,
- Drawable *candidate, Drawable *prev)
-{
- bool is_next_frame;
-
- if (candidate->stream) {
- return;
- }
-
- if (prev->stream) {
- VideoStream *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) {
- before_reattach_stream(display, stream, candidate);
- video_stream_detach_drawable(stream);
- prev->streamable = FALSE; //prevent item trace
- attach_stream(display, candidate, 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) {
- video_stream_add_frame(display, candidate,
- prev->first_frame_time,
- prev->frames_count,
- prev->gradual_frames_count,
- prev->last_gradual_frame);
- }
- }
-}
-
static void dcc_update_streams_max_latency(DisplayChannelClient *dcc,
VideoStreamAgent *remove_agent)
{
@@ -924,23 +566,3 @@ void video_stream_timeout(DisplayChannel *display)
}
}
-void video_stream_trace_add_drawable(DisplayChannel *display,
- Drawable *item)
-{
- ItemTrace *trace;
-
- if (item->stream || !item->streamable) {
- return;
- }
-
- trace = &display->priv->items_trace[display->priv->next_item_trace++ & ITEMS_TRACE_MASK];
- trace->time = item->creation_time;
- trace->first_frame_time = item->first_frame_time;
- trace->frames_count = item->frames_count;
- trace->gradual_frames_count = item->gradual_frames_count;
- trace->last_gradual_frame = item->last_gradual_frame;
- SpiceRect* src_area = &item->red_drawable->u.copy.src_area;
- trace->width = src_area->right - src_area->left;
- trace->height = src_area->bottom - src_area->top;
- trace->dest_area = item->red_drawable->bbox;
-}
diff --git a/server/video-stream.h b/server/video-stream.h
index 88d59c848..e5a35dd89 100644
--- a/server/video-stream.h
+++ b/server/video-stream.h
@@ -130,12 +130,8 @@ struct VideoStream {
void video_stream_stop(VideoStream *stream);
void video_stream_unref(VideoStream *stream);
-void video_stream_trace_update(DisplayChannel *display, Drawable *drawable);
-void video_stream_maintenance(DisplayChannel *display, Drawable *candidate,
- Drawable *prev);
void video_stream_timeout(DisplayChannel *display);
void video_stream_detach_and_stop(DisplayChannel *display);
-void video_stream_trace_add_drawable(DisplayChannel *display, Drawable *item);
void video_stream_detach_behind(DisplayChannel *display, QRegion *region,
Drawable *drawable);
--
2.13.6
More information about the Spice-devel
mailing list