[Spice-devel,v5] server: Provide a framerate estimate based on the initial frames

Submitted by Francois Gouget on Nov. 23, 2015, 3:34 p.m.

Details

Message ID alpine.DEB.2.20.1511231628380.9799@amboise
State New
Headers show
Series "server: Provide a framerate estimate based on the initial frames" ( rev: 4 ) in Spice

Not browsing as part of any series.

Commit Message

Francois Gouget Nov. 23, 2015, 3:34 p.m.
This way the video encoder can actually count on a real estimate when
it is initializing.

Signed-off-by: Francois Gouget <fgouget@codeweavers.com>
---
 server/display-channel.h |  1 +
 server/red_worker.c      |  3 ++-
 server/stream.c          | 20 +++++++++++++++++---
 server/stream.h          |  1 +
 4 files changed, 21 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

diff --git a/server/display-channel.h b/server/display-channel.h
index 03834fa..c1b56e5 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -67,6 +67,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;
diff --git a/server/red_worker.c b/server/red_worker.c
index f700829..275e707 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -644,6 +644,7 @@  static void display_stream_trace_add_drawable(DisplayChannel *display, Drawable
 
     trace = &display->items_trace[display->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;
@@ -1170,7 +1171,7 @@  static Drawable *get_drawable(RedWorker *worker, uint8_t effect, RedDrawable *re
 
     bzero(drawable, sizeof(Drawable));
     drawable->refs = 1;
-    drawable->creation_time = red_get_monotonic_time();
+    drawable->creation_time = drawable->first_frame_time = red_get_monotonic_time();
     ring_item_init(&drawable->list_link);
     ring_item_init(&drawable->surface_list_link);
     ring_item_init(&drawable->tree_item.base.siblings_link);
diff --git a/server/stream.c b/server/stream.c
index 518e2d8..ab58d0a 100644
--- a/server/stream.c
+++ b/server/stream.c
@@ -369,7 +369,16 @@  static void display_channel_create_stream(DisplayChannel *display, Drawable *dra
     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;
+    if (duration > (uint64_t)drawable->frames_count * 1000 * 1000 * 1000 / MAX_FPS) {
+        stream->input_fps = ((uint64_t)drawable->frames_count * 1000 * 1000 * 1000 + duration / 2) / duration;
+    } else {
+        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;
@@ -377,21 +386,24 @@  static void display_channel_create_stream(DisplayChannel *display, Drawable *dra
     FOREACH_DCC(display, dcc_ring_item, next, dcc) {
         dcc_create_stream(dcc, stream);
     }
-    spice_debug("stream %d %dx%d (%d, %d) (%d, %d)",
+    spice_debug("stream %d %dx%d (%d, %d) (%d, %d) %u fps",
                 (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);
+                stream->dest_area.right, stream->dest_area.bottom,
+                stream->input_fps);
     return;
 }
 
 // returns whether a stream was created
 static int 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;
 
@@ -458,6 +470,7 @@  void stream_trace_update(DisplayChannel *display, Drawable *drawable)
                                        &trace->dest_area, trace->time, NULL, FALSE) !=
                                        STREAM_FRAME_NONE) {
             if (stream_add_frame(display, drawable,
+                                 trace->first_frame_time,
                                  trace->frames_count,
                                  trace->gradual_frames_count,
                                  trace->last_gradual_frame)) {
@@ -503,6 +516,7 @@  void stream_maintenance(DisplayChannel *display,
                                  FALSE);
         if (is_next_frame != STREAM_FRAME_NONE) {
             stream_add_frame(display, candidate,
+                             prev->first_frame_time,
                              prev->frames_count,
                              prev->gradual_frames_count,
                              prev->last_gradual_frame);
diff --git a/server/stream.h b/server/stream.h
index 65de2f4..32c8d69 100644
--- a/server/stream.h
+++ b/server/stream.h
@@ -114,6 +114,7 @@  void                  stream_clip_item_unref                        (DisplayChan
 
 typedef struct ItemTrace {
     red_time_t time;
+    red_time_t first_frame_time;
     int frames_count;
     int gradual_frames_count;
     int last_gradual_frame;

Comments

Hi Francois,

Just to be sure, no difference between v4 and v5, right?

On Mon, Nov 23, 2015 at 04:34:49PM +0100, Francois Gouget wrote:
> This way the video encoder can actually count on a real estimate when
> it is initializing.
>

Could you please add part of your reply to Frediano in the commit log?
http://lists.freedesktop.org/archives/spice-devel/2015-November/023608.html

Patch seems good with the change included in v4 but I would wait an ack
from Frediano as he already reviewed it before.

Reviewed-by: Victor Toso <victortoso@redhat.com>

> Signed-off-by: Francois Gouget <fgouget@codeweavers.com>
> ---
>  server/display-channel.h |  1 +
>  server/red_worker.c      |  3 ++-
>  server/stream.c          | 20 +++++++++++++++++---
>  server/stream.h          |  1 +
>  4 files changed, 21 insertions(+), 4 deletions(-)
> 
> diff --git a/server/display-channel.h b/server/display-channel.h
> index 03834fa..c1b56e5 100644
> --- a/server/display-channel.h
> +++ b/server/display-channel.h
> @@ -67,6 +67,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;
> diff --git a/server/red_worker.c b/server/red_worker.c
> index f700829..275e707 100644
> --- a/server/red_worker.c
> +++ b/server/red_worker.c
> @@ -644,6 +644,7 @@ static void display_stream_trace_add_drawable(DisplayChannel *display, Drawable
>  
>      trace = &display->items_trace[display->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;
> @@ -1170,7 +1171,7 @@ static Drawable *get_drawable(RedWorker *worker, uint8_t effect, RedDrawable *re
>  
>      bzero(drawable, sizeof(Drawable));
>      drawable->refs = 1;
> -    drawable->creation_time = red_get_monotonic_time();
> +    drawable->creation_time = drawable->first_frame_time = red_get_monotonic_time();
>      ring_item_init(&drawable->list_link);
>      ring_item_init(&drawable->surface_list_link);
>      ring_item_init(&drawable->tree_item.base.siblings_link);
> diff --git a/server/stream.c b/server/stream.c
> index 518e2d8..ab58d0a 100644
> --- a/server/stream.c
> +++ b/server/stream.c
> @@ -369,7 +369,16 @@ static void display_channel_create_stream(DisplayChannel *display, Drawable *dra
>      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;
> +    if (duration > (uint64_t)drawable->frames_count * 1000 * 1000 * 1000 / MAX_FPS) {
> +        stream->input_fps = ((uint64_t)drawable->frames_count * 1000 * 1000 * 1000 + duration / 2) / duration;
> +    } else {
> +        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;
> @@ -377,21 +386,24 @@ static void display_channel_create_stream(DisplayChannel *display, Drawable *dra
>      FOREACH_DCC(display, dcc_ring_item, next, dcc) {
>          dcc_create_stream(dcc, stream);
>      }
> -    spice_debug("stream %d %dx%d (%d, %d) (%d, %d)",
> +    spice_debug("stream %d %dx%d (%d, %d) (%d, %d) %u fps",
>                  (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);
> +                stream->dest_area.right, stream->dest_area.bottom,
> +                stream->input_fps);
>      return;
>  }
>  
>  // returns whether a stream was created
>  static int 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;
>  
> @@ -458,6 +470,7 @@ void stream_trace_update(DisplayChannel *display, Drawable *drawable)
>                                         &trace->dest_area, trace->time, NULL, FALSE) !=
>                                         STREAM_FRAME_NONE) {
>              if (stream_add_frame(display, drawable,
> +                                 trace->first_frame_time,
>                                   trace->frames_count,
>                                   trace->gradual_frames_count,
>                                   trace->last_gradual_frame)) {
> @@ -503,6 +516,7 @@ void stream_maintenance(DisplayChannel *display,
>                                   FALSE);
>          if (is_next_frame != STREAM_FRAME_NONE) {
>              stream_add_frame(display, candidate,
> +                             prev->first_frame_time,
>                               prev->frames_count,
>                               prev->gradual_frames_count,
>                               prev->last_gradual_frame);
> diff --git a/server/stream.h b/server/stream.h
> index 65de2f4..32c8d69 100644
> --- a/server/stream.h
> +++ b/server/stream.h
> @@ -114,6 +114,7 @@ void                  stream_clip_item_unref                        (DisplayChan
>  
>  typedef struct ItemTrace {
>      red_time_t time;
> +    red_time_t first_frame_time;
>      int frames_count;
>      int gradual_frames_count;
>      int last_gradual_frame;
> -- 
> 2.6.2
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel