[Spice-devel] [PATCH spice-server 07/28] mjpeg_encoder: update the client with estimations for the required playback latency
Alon Levy
alevy at redhat.com
Sun Apr 14 06:20:49 PDT 2013
On Tue, Feb 26, 2013 at 01:03:53PM -0500, Yonit Halperin wrote:
> The required client playback latency is assessed based on the current
> estimation of the bit rate, the network latency, and the encoding size
> of the frames. When the playback delay that is reported by the client
> seems too small, or when the stream parameters change, we send the
> client an updated playback latency estimation.
ACK.
> ---
> server/mjpeg_encoder.c | 51 ++++++++++++++++++++++++++++++++++++--------------
> server/mjpeg_encoder.h | 1 +
> 2 files changed, 38 insertions(+), 14 deletions(-)
>
> diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
> index d50a5d1..70b6338 100644
> --- a/server/mjpeg_encoder.c
> +++ b/server/mjpeg_encoder.c
> @@ -51,6 +51,12 @@ static const int mjpeg_quality_samples[MJPEG_QUALITY_SAMPLE_NUM] = {20, 30, 40,
> #define MJPEG_CLIENT_POSITIVE_REPORT_TIMEOUT 2000
> #define MJPEG_CLIENT_POSITIVE_REPORT_STRICT_TIMEOUT 3000
>
> +/*
> + * avoid interrupting the playback when there are temporary
> + * incidents of instability (with respect to server and client drops)
> + */
> +#define MJPEG_MAX_CLIENT_PLAYBACK_DELAY 5000 // 5 sec
> +
> enum {
> MJPEG_QUALITY_EVAL_TYPE_SET,
> MJPEG_QUALITY_EVAL_TYPE_UPGRADE,
> @@ -151,6 +157,9 @@ static inline void mjpeg_encoder_reset_quality(MJpegEncoder *encoder,
> uint64_t frame_enc_size);
> static uint32_t get_max_fps(uint64_t frame_size, uint64_t bytes_per_sec, uint32_t latency_ms);
> static void mjpeg_encoder_process_server_drops(MJpegEncoder *encoder);
> +static uint32_t get_min_required_playback_delay(uint64_t frame_enc_size,
> + uint64_t byte_rate,
> + uint32_t latency);
>
> MJpegEncoder *mjpeg_encoder_new(int bit_rate_control, uint64_t starting_bit_rate,
> MJpegEncoderRateControlCbs *cbs, void *opaque)
> @@ -503,6 +512,13 @@ complete_sample:
>
> spice_debug("MJpeg quality sample end %p: quality %d fps %d",
> encoder, mjpeg_quality_samples[rate_control->quality_id], rate_control->fps);
> + if (encoder->cbs.update_client_playback_delay) {
> + uint32_t min_delay = get_min_required_playback_delay(final_quality_enc_size,
> + rate_control->byte_rate,
> + latency);
> +
> + encoder->cbs.update_client_playback_delay(encoder->cbs_opaque, min_delay);
> + }
> }
>
> static void mjpeg_encoder_quality_eval_set_upgrade(MJpegEncoder *encoder,
> @@ -965,13 +981,15 @@ static uint32_t get_min_required_playback_delay(uint64_t frame_enc_size,
> uint32_t latency)
> {
> uint32_t one_frame_time;
> + uint32_t min_delay;
>
> if (!frame_enc_size || !byte_rate) {
> return latency;
> }
> one_frame_time = (frame_enc_size*1000)/byte_rate;
>
> - return one_frame_time*2 + latency;
> + min_delay = MIN(one_frame_time*2 + latency, MJPEG_MAX_CLIENT_PLAYBACK_DELAY);
> + return min_delay;
> }
>
> #define MJPEG_PLAYBACK_LATENCY_DECREASE_FACTOR 0.5
> @@ -990,6 +1008,7 @@ void mjpeg_encoder_client_stream_report(MJpegEncoder *encoder,
> MJpegEncoderClientState *client_state = &rate_control->client_state;
> uint64_t avg_enc_size = 0;
> uint32_t min_playback_delay;
> + int is_video_delay_small = FALSE;
>
> spice_debug("client report: #frames %u, #drops %d, duration %u video-delay %d audio-delay %u",
> num_frames, num_drops,
> @@ -1017,6 +1036,23 @@ void mjpeg_encoder_client_stream_report(MJpegEncoder *encoder,
> mjpeg_encoder_get_latency(encoder));
> spice_debug("min-delay %u client-delay %d", min_playback_delay, end_frame_delay);
>
> + if (min_playback_delay > end_frame_delay) {
> + uint32_t src_fps = encoder->cbs.get_source_fps(encoder->cbs_opaque);
> + /*
> + * if the stream is at its highest rate, we can't estimate the "real"
> + * network bit rate and the min_playback_delay
> + */
> + if (rate_control->quality_id != MJPEG_QUALITY_SAMPLE_NUM - 1 ||
> + rate_control->fps < MIN(src_fps, MJPEG_MAX_FPS) || end_frame_delay < 0) {
> + is_video_delay_small = TRUE;
> + if (encoder->cbs.update_client_playback_delay) {
> + encoder->cbs.update_client_playback_delay(encoder->cbs_opaque,
> + min_playback_delay);
> + }
> + }
> + }
> +
> +
> /*
> * If the audio latency has decreased (since the start of the current
> * sequence of positive reports), and the video latency is bigger, slow down
> @@ -1036,25 +1072,12 @@ void mjpeg_encoder_client_stream_report(MJpegEncoder *encoder,
> mjpeg_encoder_handle_negative_client_stream_report(encoder,
> end_frame_mm_time);
> } else {
> - int is_video_delay_small = FALSE;
> double major_delay_decrease_thresh;
> double medium_delay_decrease_thresh;
>
> client_state->max_video_latency = MAX(end_frame_delay, client_state->max_video_latency);
> client_state->max_audio_latency = MAX(audio_delay, client_state->max_audio_latency);
>
> - if (min_playback_delay > end_frame_delay) {
> - uint32_t src_fps = encoder->cbs.get_source_fps(encoder->cbs_opaque);
> - /*
> - * if the stream is at its highest rate, we can't estimate the "real"
> - * network bit rate and the min_playback_delay
> - */
> - if (rate_control->quality_id != MJPEG_QUALITY_SAMPLE_NUM - 1 ||
> - rate_control->fps < MIN(src_fps, MJPEG_MAX_FPS)) {
> - is_video_delay_small = TRUE;
> - }
> - }
> -
> medium_delay_decrease_thresh = client_state->max_video_latency;
> medium_delay_decrease_thresh *= MJPEG_PLAYBACK_LATENCY_DECREASE_FACTOR;
>
> diff --git a/server/mjpeg_encoder.h b/server/mjpeg_encoder.h
> index bc7f01c..f9ae43c 100644
> --- a/server/mjpeg_encoder.h
> +++ b/server/mjpeg_encoder.h
> @@ -34,6 +34,7 @@ typedef struct MJpegEncoder MJpegEncoder;
> typedef struct MJpegEncoderRateControlCbs {
> uint32_t (*get_roundtrip_ms)(void *opaque);
> uint32_t (*get_source_fps)(void *opaque);
> + void (*update_client_playback_delay)(void *opaque, uint32_t delay_ms);
> } MJpegEncoderRateControlCbs;
>
> MJpegEncoder *mjpeg_encoder_new(int bit_rate_control, uint64_t starting_bit_rate,
> --
> 1.8.1
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
More information about the Spice-devel
mailing list