<html><head></head><body><div style="color:#000; background-color:#fff; font-family:HelveticaNeue, Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif;font-size:16px"><div><span>So one thing I notice is that there is a multimedia audio device that has a bad driver in the device manager... maybe that is screwing things up, forcing the video to wait for audio that will never come... I'll see if i can get that working properly and maybe it will help. </span></div><div class="qtdSeparateBR"><br><br></div><div class="yahoo_quoted" id="yui_3_16_0_ym19_1_1476381488636_2948" style="display: block;"> <div style="font-family: HelveticaNeue, Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif; font-size: 16px;" id="yui_3_16_0_ym19_1_1476381488636_2947"> <div style="font-family: HelveticaNeue, Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif; font-size: 16px;" id="yui_3_16_0_ym19_1_1476381488636_2946"> <div dir="ltr" id="yui_3_16_0_ym19_1_1476381488636_2945"> <font size="2" face="Arial" id="yui_3_16_0_ym19_1_1476381488636_2991"> <hr size="1"> <b><span style="font-weight:bold;">From:</span></b> Frediano Ziglio <fziglio@redhat.com><br> <b><span style="font-weight: bold;">To:</span></b> Brad Wilson <bradwilsonstl@yahoo.com> <br><b><span style="font-weight: bold;">Cc:</span></b> spice-devel@lists.freedesktop.org<br> <b><span style="font-weight: bold;">Sent:</span></b> Thursday, October 13, 2016 10:08 AM<br> <b><span style="font-weight: bold;">Subject:</span></b> Re: [Spice-devel] Very poor video performance using Virt Viewer compared to RDP<br> </font> </div> <div class="y_msg_container" id="yui_3_16_0_ym19_1_1476381488636_2949"><br>> I have a Windows 7 VM running via Qemu on Gentoo Linux using a product called<br clear="none">> Foss-Cloud.<br clear="none">> I have spice tools and the QXL video driver installed<br clear="none">> Using Virt-Viewer The Vm shows a little lag when typing (always takes a<br clear="none">> second to catch up when typing my password to log in and such). In general<br clear="none">> pulling up folders and text heavy web pages is pretty snappy and doesn’t tax<br clear="none">> the cpu or memory at all. If look at a site that has a lot of pictures I<br clear="none">> start seeing frame loss and the mouse gets a little laggy when scrolling. If<br clear="none">> I pull up a video I see the cpu jump a little and the video is extremely<br clear="none">> laggy and I see about ever 10 th frame of the video, at the same time I lose<br clear="none">> sight of the mouse pointer for a second at a time and it becomes hard to<br clear="none">> control.<br clear="none">> While connecting to this vm using Virt-Viewer I also notice very low<br clear="none">> bandwidth usage, well below 500Kbps which is strange for a remote session<br clear="none">> sending video traffic.<br clear="none">> Using Windows RDP I was able to pull up all the same videos and web pages<br clear="none">> with no problem, the videos were clear and ran smooth and the websites with<br clear="none">> a lot of pictures scrolled normally. I did notice that the network traffic<br clear="none">> using RDP was closer to 10mbps and spiked to 14mbps so it’s understandable<br clear="none">> that I would get a better experience.<br clear="none"><br clear="none">I'm not really familiar with the client code and I don't know if this<br clear="none">is really related to your problem but it share the fact of the lag and<div class="yqt2042709339" id="yqtfd44609"><br clear="none">the video.</div><br clear="none"><br clear="none">While I was trying to code Virgl remote support I noted that in some<br clear="none">conditions I had EXTREME (like 1/2 seconds) lags. This was worsened<br clear="none">with low bandwidth. I started putting some debug code to understand<br clear="none">if server was queueing too data or was just too slow to handle the<br clear="none">encoding. And if was fast enough to handle all encoded frames and<br clear="none">the code in the streaming to deal with low bandwidth was apparently<br clear="none">doing it's job and the network queue (you can see with netstat) was<br clear="none">low. I then started putting timestamps in the frames trying to<br clear="none">understand where the lag was coming from and how much time take from<br clear="none">the encoding to the final client screen (you can see a video at<br clear="none"><a shape="rect" href="https://www.youtube.com/watch?v=D_DCs2sriu0" target="_blank">https://www.youtube.com/watch?v=D_DCs2sriu0 </a>to understand the<br clear="none">time stamping, the green time in the video was written in the frames<br clear="none">before encoding in the server, not by the client).<br clear="none"><br clear="none">I discovered where the main lag came quite by "accident". To test<br clear="none">I used one small utility and this utility don't have a way to change<br clear="none">parameters (like bandwidth) so knowing how the tcp work I stopped<br clear="none">the utility and started again as fast as I can with different<br clear="none">parameters. This of course create packets loss and some delay but<br clear="none">the connection works fine as tcp retransmit the packets lost.<br clear="none">But surprisingly the delay introduced by this accident was maintained<br clear="none">in the video! I then removed all Virgl stuff, tried again with a video<br clear="none">and the lag is still present. Also interrupting the utility and<br clear="none">starting again was increasing the lag (I managed to have about<br clear="none">3 seconds lag!).<br clear="none"><br clear="none">Now... I have a patch for the client but as I said I'm not familiar<br clear="none">with the client too much and it's really terrible. It mainly remove<br clear="none">the synchronization with the audio (with still lags) and play the<br clear="none">video as fast as possible. By the way, I think is time to send as<br clear="none">someone could be able to make a sensible version of this patch<br clear="none">(perhaps fixing the sound too)<br clear="none"><br clear="none"><br clear="none">From 31364b1b1b1e5041ba64441f18104f7f1e978af5 Mon Sep 17 00:00:00 2001<br clear="none">From: Frediano Ziglio <<a shape="rect" ymailto="mailto:fziglio@redhat.com" href="mailto:fziglio@redhat.com">fziglio@redhat.com</a>><br clear="none">Date: Thu, 13 Oct 2016 15:40:49 +0100<br clear="none">Subject: [spice-gtk] Try to reduce video lag<br clear="none"><br clear="none">---<br clear="none"> src/channel-display-gst.c | 26 ++++++++++++++++----------<br clear="none"> 1 file changed, 16 insertions(+), 10 deletions(-)<br clear="none"><br clear="none">diff --git a/src/channel-display-gst.c b/src/channel-display-gst.c<br clear="none">index 430bb95..c1ebfeb 100644<br clear="none">--- a/src/channel-display-gst.c<br clear="none">+++ b/src/channel-display-gst.c<br clear="none">@@ -48,6 +48,7 @@ typedef struct SpiceGstDecoder {<br clear="none"> GQueue *decoding_queue;<br clear="none"> GQueue *display_queue;<br clear="none"> guint timer_id;<br clear="none">+ guint unique_id;<br clear="none"> } SpiceGstDecoder;<br clear="none"> <br clear="none"> <br clear="none">@@ -94,13 +95,15 @@ static gboolean display_frame(gpointer video_decoder)<br clear="none"> GstBuffer *buffer;<br clear="none"> GstMapInfo mapinfo;<br clear="none"> <br clear="none">- decoder->timer_id = 0;<br clear="none">-<br clear="none">+ again:<br clear="none"> g_mutex_lock(&decoder->queues_mutex);<br clear="none">+ decoder->timer_id = 0;<br clear="none"> frame = g_queue_pop_head(decoder->display_queue);<br clear="none"> g_mutex_unlock(&decoder->queues_mutex);<br clear="none"> /* If the queue is empty we don't even need to reschedule */<br clear="none">- g_return_val_if_fail(frame, G_SOURCE_REMOVE);<br clear="none">+ if (!frame) {<br clear="none">+ return G_SOURCE_REMOVE;<br clear="none">+ }<br clear="none"> <br clear="none"> if (!frame->sample) {<br clear="none"> spice_warning("got a frame without a sample!");<br clear="none">@@ -132,26 +135,28 @@ static gboolean display_frame(gpointer video_decoder)<br clear="none"> <br clear="none"> error:<br clear="none"> free_frame(frame);<br clear="none">- schedule_frame(decoder);<br clear="none">- return G_SOURCE_REMOVE;<br clear="none">+ goto again;<br clear="none"> }<br clear="none"> <br clear="none"> /* main loop or GStreamer streaming thread */<br clear="none"> static void schedule_frame(SpiceGstDecoder *decoder)<br clear="none"> {<br clear="none">- guint32 now = stream_get_time(decoder->base.stream);<br clear="none">+// guint32 now = stream_get_time(decoder->base.stream);<br clear="none"> g_mutex_lock(&decoder->queues_mutex);<br clear="none"> <br clear="none">+ if (decoder->timer_id)<br clear="none">+ printf("not scheduling, already a timer\n");<br clear="none"> while (!decoder->timer_id) {<br clear="none"> SpiceFrame *frame = g_queue_peek_head(decoder->display_queue);<br clear="none"> if (!frame) {<br clear="none"> break;<br clear="none"> }<br clear="none"> <br clear="none">- SpiceStreamDataHeader *op = spice_msg_in_parsed(frame->msg);<br clear="none">+// SpiceStreamDataHeader *op = spice_msg_in_parsed(frame->msg);<br clear="none">+ decoder->timer_id = g_timeout_add(0, display_frame, decoder);<br clear="none">+#if 0<br clear="none"> if (now < op->multi_media_time) {<br clear="none">- decoder->timer_id = g_timeout_add(op->multi_media_time - now,<br clear="none">- display_frame, decoder);<br clear="none">+ decoder->timer_id = g_timeout_add(0, display_frame, decoder);<br clear="none"> } else if (g_queue_get_length(decoder->display_queue) == 1) {<br clear="none"> /* Still attempt to display the least out of date frame so the<br clear="none"> * video is not completely frozen for an extended period of time.<br clear="none">@@ -165,6 +170,7 @@ static void schedule_frame(SpiceGstDecoder *decoder)<br clear="none"> g_queue_pop_head(decoder->display_queue);<br clear="none"> free_frame(frame);<br clear="none"> }<br clear="none">+#endif<br clear="none"> }<br clear="none"> <br clear="none"> g_mutex_unlock(&decoder->queues_mutex);<br clear="none">@@ -415,7 +421,7 @@ static void spice_gst_decoder_queue_frame(VideoDecoder *video_decoder,<br clear="none"> <br clear="none"> GST_BUFFER_DURATION(buffer) = GST_CLOCK_TIME_NONE;<br clear="none"> GST_BUFFER_DTS(buffer) = GST_CLOCK_TIME_NONE;<br clear="none">- GST_BUFFER_PTS(buffer) = gst_clock_get_time(decoder->clock) - gst_element_get_base_time(decoder->pipeline) + ((uint64_t)MAX(0, latency)) * 1000 * 1000;<br clear="none">+ GST_BUFFER_PTS(buffer) = ++decoder->unique_id;<br clear="none"> <br clear="none"> g_mutex_lock(&decoder->queues_mutex);<br clear="none"> g_queue_push_tail(decoder->decoding_queue, create_frame(buffer, frame_msg));<br clear="none">-- <br clear="none">2.7.4<br clear="none"><br clear="none"><br clear="none">Frediano<br><br></div> </div> </div> </div></div></body></html>