This way the video encoder can actually count on a real estimate when it is initializing. Signed-off-by: Francois Gouget <fgouget@xxxxxxxxxxxxxxx> --- Initialisation time is when video encoders need an fps most since they have no other information at that point. Yet, all they were getting is MAX_FPS (30). This patch takes advantage of the fact that Spice needs to keep track of the related drawables in order to determine whether creating a video stream makes sense. So it stores the time of the first drawable and then propagates it. So when the time comes to create the stream we can provide a framerate estimate based on the first 20 frames. In my tests the result falls within one 1 fps of the later estimates and thus is much more useful than MAX_FPS. server/red_worker.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/server/red_worker.c b/server/red_worker.c index a07a78a..8374f54 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -844,6 +844,7 @@ struct Drawable { Ring glz_ring; red_time_t creation_time; + red_time_t first_frame_time; int frames_count; int gradual_frames_count; int last_gradual_frame; @@ -915,6 +916,7 @@ typedef struct RedSurface { typedef struct ItemTrace { red_time_t time; + red_time_t first_frame_time; int frames_count; int gradual_frames_count; int last_gradual_frame; @@ -1926,6 +1928,7 @@ static inline void red_add_item_trace(RedWorker *worker, Drawable *item) trace = &worker->items_trace[worker->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; @@ -3155,7 +3158,12 @@ static void red_create_stream(RedWorker *worker, Drawable *drawable) 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; + /* 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; + stream->input_fps = ((uint64_t)drawable->frames_count * 1000 * 1000 * 1000 + duration / 2) / duration; stream->num_input_frames = 0; stream->input_fps_start_time = drawable->creation_time; worker->streams_size_total += stream->width * stream->height; @@ -3163,9 +3171,9 @@ static void red_create_stream(RedWorker *worker, Drawable *drawable) WORKER_FOREACH_DCC_SAFE(worker, dcc_ring_item, next, dcc) { red_display_create_stream(dcc, stream); } - spice_debug("stream %d %dx%d (%d, %d) (%d, %d)", (int)(stream - worker->streams_buf), stream->width, + spice_debug("stream %d %dx%d (%d, %d) (%d, %d) %u fps", (int)(stream - worker->streams_buf), stream->width, stream->height, stream->dest_area.left, stream->dest_area.top, - stream->dest_area.right, stream->dest_area.bottom); + stream->dest_area.right, stream->dest_area.bottom, stream->input_fps); return; } @@ -3419,11 +3427,13 @@ static inline int red_is_stream_start(Drawable *drawable) // returns whether a stream was created static int red_stream_add_frame(RedWorker *worker, Drawable *frame_drawable, + red_time_t first_frame_time, int frames_count, int gradual_frames_count, int last_gradual_frame) { red_update_copy_graduality(worker, 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; @@ -3477,6 +3487,7 @@ static inline void red_stream_maintenance(RedWorker *worker, Drawable *candidate } else { if (red_is_next_stream_frame(worker, candidate, prev) != STREAM_FRAME_NONE) { red_stream_add_frame(worker, candidate, + prev->first_frame_time, prev->frames_count, prev->gradual_frames_count, prev->last_gradual_frame); @@ -3638,6 +3649,7 @@ static inline void red_use_stream_trace(RedWorker *worker, Drawable *drawable) &trace->dest_area, trace->time, NULL, FALSE) != STREAM_FRAME_NONE) { if (red_stream_add_frame(worker, drawable, + trace->first_frame_time, trace->frames_count, trace->gradual_frames_count, trace->last_gradual_frame)) { @@ -4099,7 +4111,7 @@ static Drawable *get_drawable(RedWorker *worker, uint8_t effect, RedDrawable *re memset(drawable, 0, sizeof(Drawable)); drawable->refs = 1; clock_gettime(CLOCK_MONOTONIC, &time); - drawable->creation_time = timespec_to_red_time(&time); + drawable->creation_time = drawable->first_frame_time = timespec_to_red_time(&time); #ifdef PIPE_DEBUG drawable->tree_item.base.id = ++worker->last_id; #endif -- 2.1.4 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel