[Spice-devel] [PATCH spice-server 10/28] mjpeg_encoder: add stream warmup time, in which we avoid server and client drops

Yonit Halperin yhalperi at redhat.com
Tue Feb 26 10:03:56 PST 2013


The stream starts after lossless frames were sent to the client,
and without rate control (except for pipe congestion). Thus, on the beginning
of the stream, we might observe frame drops on the client and server side which
are not necessarily related to mis-estimation of the bit rate, and we would
like to wait till the stream stabilizes.
---
 server/mjpeg_encoder.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
index 037a232..277794b 100644
--- a/server/mjpeg_encoder.c
+++ b/server/mjpeg_encoder.c
@@ -59,6 +59,15 @@ static const int mjpeg_quality_samples[MJPEG_QUALITY_SAMPLE_NUM] = {20, 30, 40,
  */
 #define MJPEG_MAX_CLIENT_PLAYBACK_DELAY 5000 // 5 sec
 
+/*
+ * The stream starts after lossless frames were sent to the client,
+ * and without rate control (except for pipe congestion). Thus, on the beginning
+ * of the stream, we might observe frame drops on the client and server side which
+ * are not necessarily related to mis-estimation of the bit rate, and we would
+ * like to wait till the stream stabilizes.
+ */
+#define MJPEG_WARMUP_TIME 3000L // 3 sec
+
 enum {
     MJPEG_QUALITY_EVAL_TYPE_SET,
     MJPEG_QUALITY_EVAL_TYPE_UPGRADE,
@@ -140,6 +149,7 @@ typedef struct MJpegEncoderRateControl {
     uint64_t sum_recent_enc_size;
     uint32_t num_recent_enc_frames;
 
+    uint64_t warmup_start_time;
 } MJpegEncoderRateControl;
 
 struct MJpegEncoder {
@@ -182,12 +192,16 @@ MJpegEncoder *mjpeg_encoder_new(int bit_rate_control, uint64_t starting_bit_rate
     enc->rate_control_is_active = bit_rate_control;
     enc->rate_control.byte_rate = starting_bit_rate / 8;
     if (bit_rate_control) {
+        struct timespec time;
+
+        clock_gettime(CLOCK_MONOTONIC, &time);
         enc->cbs = *cbs;
         enc->cbs_opaque = opaque;
         mjpeg_encoder_reset_quality(enc, MJPEG_QUALITY_SAMPLE_NUM / 2, 5, 0);
         enc->rate_control.during_quality_eval = TRUE;
         enc->rate_control.quality_eval_data.type = MJPEG_QUALITY_EVAL_TYPE_SET;
         enc->rate_control.quality_eval_data.reason = MJPEG_QUALITY_EVAL_REASON_RATE_CHANGE;
+        enc->rate_control.warmup_start_time = ((uint64_t) time.tv_sec) * 1000000000 + time.tv_nsec;
     } else {
         mjpeg_encoder_reset_quality(enc, MJPEG_LEGACY_STATIC_QUALITY_ID, MJPEG_MAX_FPS, 0);
     }
@@ -894,6 +908,19 @@ static void mjpeg_encoder_decrease_bit_rate(MJpegEncoder *encoder)
 
     rate_control->client_state.max_video_latency = 0;
     rate_control->client_state.max_audio_latency = 0;
+    if (rate_control->warmup_start_time) {
+        struct timespec time;
+        uint64_t now;
+
+        clock_gettime(CLOCK_MONOTONIC, &time);
+        now = ((uint64_t) time.tv_sec) * 1000000000 + time.tv_nsec;
+        if (now - rate_control->warmup_start_time < MJPEG_WARMUP_TIME*1000*1000) {
+            spice_debug("during warmup. ignoring");
+            return;
+        } else {
+            rate_control->warmup_start_time = 0;
+        }
+    }
 
     if (bit_rate_info->num_enc_frames > MJPEG_BIT_RATE_EVAL_MIN_NUM_FRAMES ||
         bit_rate_info->num_enc_frames > rate_control->fps) {
-- 
1.8.1



More information about the Spice-devel mailing list