diff options
author | Yonit Halperin <yhalperi@redhat.com> | 2013-02-20 21:01:22 -0500 |
---|---|---|
committer | Yonit Halperin <yhalperi@redhat.com> | 2013-04-22 16:30:53 -0400 |
commit | 622d7159c26876d9a579b0dadee52091a87220b9 (patch) | |
tree | 7e1625725842f74cc9930509452bc7a50a208a88 /server/mjpeg_encoder.c | |
parent | ff1bde1d81d3f28c9079e8c274748253eb93b8d8 (diff) | |
download | spice-622d7159c26876d9a579b0dadee52091a87220b9.tar.gz spice-622d7159c26876d9a579b0dadee52091a87220b9.tar.xz spice-622d7159c26876d9a579b0dadee52091a87220b9.zip |
mjpeg_encoder: add stream warmup time, in which we avoid server and client drops
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.
Diffstat (limited to 'server/mjpeg_encoder.c')
-rw-r--r-- | server/mjpeg_encoder.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c index 41d234ec..7328ea26 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); } @@ -904,6 +918,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) { |