--- server/mjpeg_encoder.c | 7 +++++ server/red_worker.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c index 7825955..b5faed6 100644 --- a/server/mjpeg_encoder.c +++ b/server/mjpeg_encoder.c @@ -167,6 +167,10 @@ struct MJpegEncoder { MJpegEncoderRateControl rate_control; MJpegEncoderRateControlCbs cbs; void *cbs_opaque; + + /* stats */ + uint64_t avg_quality; + uint32_t num_frames; }; static inline void mjpeg_encoder_reset_quality(MJpegEncoder *encoder, @@ -214,6 +218,7 @@ MJpegEncoder *mjpeg_encoder_new(int bit_rate_control, uint64_t starting_bit_rate void mjpeg_encoder_destroy(MJpegEncoder *encoder) { + spice_debug("avg-quality %.2f", (double)encoder->avg_quality / encoder->num_frames); jpeg_destroy_compress(&encoder->cinfo); free(encoder->row); free(encoder); @@ -805,6 +810,8 @@ int mjpeg_encoder_start_frame(MJpegEncoder *encoder, SpiceBitmapFmt format, jpeg_set_quality(&encoder->cinfo, quality, TRUE); jpeg_start_compress(&encoder->cinfo, encoder->first_frame); + encoder->num_frames++; + encoder->avg_quality += quality; return MJPEG_ENCODER_FRAME_ENCODE_START; } diff --git a/server/red_worker.c b/server/red_worker.c index deb375c..2cb9f62 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -449,6 +449,20 @@ struct Stream { uint32_t input_fps; }; +#define STREAM_STATS +#ifdef STREAM_STATS +typedef struct StreamStats { + uint64_t num_drops_pipe; + uint64_t num_drops_fps; + uint64_t num_frames_sent; + uint64_t num_input_frames; + uint64_t size_sent; + + uint64_t start; + uint64_t end; +} StreamStats; +#endif + typedef struct StreamAgent { QRegion vis_region; /* the part of the surface area that is currently occupied by video fragments */ @@ -472,6 +486,9 @@ typedef struct StreamAgent { uint32_t report_id; uint32_t client_required_latency; +#ifdef STREAM_STATS + StreamStats stats; +#endif } StreamAgent; typedef struct StreamClipItem { @@ -2599,9 +2616,38 @@ static void red_attach_stream(RedWorker *worker, Drawable *drawable, Stream *str region_or(&agent->clip, &drawable->tree_item.base.rgn); push_stream_clip(dcc, agent); } +#ifdef STREAM_STATS + agent->stats.num_input_frames++; +#endif } } +static void red_print_stream_stats(DisplayChannelClient *dcc, StreamAgent *agent) +{ +#ifdef STREAM_STATS + StreamStats *stats = &agent->stats; + double passed_mm_time = (stats->end - stats->start) / 1000.0; + + spice_debug("stream %ld (%dx%d): #frames-sent %lu, #drops %lu (pipe %lu, fps %lu), avg_fps %.2f," + "passed mm-time %.2f (sec), size %.2f (KB) %.2f (Mbps) %.2f (KBpf)", + agent - dcc->stream_agents, agent->stream->width, agent->stream->height, + stats->num_frames_sent, + stats->num_drops_pipe + + stats->num_drops_fps, + stats->num_drops_pipe, + stats->num_drops_fps, + stats->num_frames_sent / passed_mm_time, + passed_mm_time, + stats->size_sent / 1024.0, + ((stats->size_sent * 8.0) / (1024.0 * 1024)) / passed_mm_time, + stats->size_sent / 1000.0 / stats->num_frames_sent); + spice_debug("num-input-frames %lu, per-sec %.2f, prec-frames-sent %.2f (out/in)", + stats->num_input_frames, + stats->num_input_frames / passed_mm_time, + (stats->num_frames_sent + 0.0) / stats->num_input_frames); +#endif +} + static void red_stop_stream(RedWorker *worker, Stream *stream) { DisplayChannelClient *dcc; @@ -2629,6 +2675,7 @@ static void red_stop_stream(RedWorker *worker, Stream *stream) } stream->refs++; red_channel_client_pipe_add(&dcc->common.base, &stream_agent->destroy_item); + red_print_stream_stats(dcc, stream_agent); } worker->streams_size_total -= stream->width * stream->height; ring_remove(&stream->link); @@ -3024,7 +3071,12 @@ static void red_display_create_stream(DisplayChannelClient *dcc, Stream *stream) report_pipe_item->stream_id = get_stream_id(dcc->common.worker, stream); red_channel_client_pipe_add(&dcc->common.base, &report_pipe_item->pipe_item); } - +#ifdef STREAM_STATS + memset(&agent->stats, 0, sizeof(StreamStats)); + if (stream->current) { + agent->stats.start = stream->current->red_drawable->mm_time; + } +#endif } static void red_stream_input_fps_timer_cb(void *opaque) @@ -3268,6 +3320,9 @@ static inline void pre_stream_item_swap(RedWorker *worker, Stream *stream, Drawa } if (pipe_item_is_linked(&dpi->dpi_pipe_item)) { +#ifdef STREAM_STATS + agent->stats.num_drops_pipe++; +#endif if (dcc->use_mjpeg_encoder_rate_control) { mjpeg_encoder_notify_server_frame_drop(agent->mjpeg_encoder); } else { @@ -8548,6 +8603,9 @@ static inline int red_marshall_stream_data(RedChannelClient *rcc, if (!dcc->use_mjpeg_encoder_rate_control) { if (time_now - agent->last_send_time < (1000 * 1000 * 1000) / agent->fps) { agent->frames--; +#ifdef STREAM_STATS + agent->stats.num_drops_fps++; +#endif return TRUE; } } @@ -8561,6 +8619,9 @@ static inline int red_marshall_stream_data(RedChannelClient *rcc, switch (ret) { case MJPEG_ENCODER_FRAME_DROP: spice_assert(dcc->use_mjpeg_encoder_rate_control); +#ifdef STREAM_STATS + agent->stats.num_drops_fps++; +#endif return TRUE; case MJPEG_ENCODER_FRAME_UNSUPPORTED: return FALSE; @@ -8606,6 +8667,12 @@ static inline int red_marshall_stream_data(RedChannelClient *rcc, spice_marshaller_add_ref(base_marshaller, dcc->send_data.stream_outbuf, n); agent->last_send_time = time_now; +#ifdef STREAM_STATS + agent->stats.num_frames_sent++; + agent->stats.size_sent += n; + agent->stats.end = drawable->red_drawable->mm_time; +#endif + return TRUE; } -- 1.8.1 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel