[Spice-devel] [PATCH spice 3/11] server: Refactor the Spice server video encoding so alternative implementations can be added.

Francois Gouget fgouget at codeweavers.com
Tue May 26 08:26:50 PDT 2015


On Tue, 19 May 2015, Marc-André Lureau wrote:
[...]
> > +struct VideoEncoder {
> > +    /* Releases the video encoder's resources */
> > +    void (*destroy)(VIDEO_ENCODER_T *encoder);
> > +
> > +    /* Compresses the specified src image area into the outbuf buffer.
> > +     *
> > +     * @encoder:   The video encoder.
> > +     * @bitmap:    The Spice screen.
> > +     * @width:     The width of the Spice screen.
> > +     * @height:    The heigth of the Spice screen.
> >
> 
> It's not the screen, it's the video area. It's not clear to me what 
> would happen if the "src" size doesn't match the width&height.

Ah right. I'll fix the comment. I was confused about that but after 
looking again I must say I'm still unsure as to why we get both src and 
width+height.

My understanding is that this has been introduced to deal with the 
YouTube progress bar:
https://bugzilla.redhat.com/show_bug.cgi?id=813826

To sum up, the size of the video area detected by the Spice server 
changes when the progress bar pops up or down. As a result some of the 
'video frames' it gets don't match the size it detected when it created 
the video stream.

 * It used to be that this caused such frames to go through the regular 
   update mechanism instead of through the video stream. This is still 
   the case with the spicec client for instance and results in the video 
   seeming to jump back and forth because the video stream is delayed 
   due to buffering while the regular path is not.

   Looking at the impact on src & height, either the size of the video 
   frame, aka src, matches the stream size and then so do width and 
   height (lines 9 & 10 below), or it does not and then we don't go 
   through the video encoder (line 6 below).


 * Now clients can advertise support for changing stream sizes with the 
   SIZED_STREAM capability. This does not totally fix the back and forth 
   issue but restricts it to the progress bar area as it comes in and 
   out of the video frame.

   In that case width & height are either computed from the actual video 
   frame size, aka src, (lines 3 & 4 below), or default to the initial 
   stream size when the video frame size matches (lines 9 & 10 below).

From red_marshall_stream_data():
 1 if (drawable->sized_stream) {
 2   if (red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_SIZED_STREAM)) {
 3     width = src_rect->right - src_rect->left;
 4     height = src_rect->bottom - src_rect->top;
 5   } else {
 6     return FALSE;
 7   }
 8 } else {
 9   width = stream->width;
10   height = stream->height;
11 }

So in the end width and height *always* match src. So they're redundant, 
unless some larger purpose is planned for them.

Now must say having a continuously changing stream size is quite 
annoying in the context of GStreamer:
 - At a minimum it forces a reconfiguration of the pipeline which, 
   depending on the encoder, may require rebuilding it. Either cases 
   seem to cause a reset of the GStreamer's encoder bitrate control 
   algorithm which tends to cause it to overshoot and may cause frame 
   drops.
 - Ultimately the GStreamer video encoder should support inter-frame 
   compression (with VP8 or H264 for instance) and a changing stream 
   size will also cause some disruption in this context.

Things can still work as is so there's not hurry but maybe a better 
solution can be devised in time.


For instance it may be better to increase the stream size as the video 
frame size increases but then peg it so it does not shrink again. This 
would solve the remaining back and forth issue with the YouTube progress 
bar, and limit the number of resizes the video encoders have to go 
through. It supposes that regular frame updates know to ignore changes 
happening inside the stream area even if they don't go through the 
regular 'video frame' update path but I have no idea if that's easy to 
do.

Alternatively one could split oversize video frames in two: the stream 
area which would go through the video encoder, and the remainder which 
would go through the regular path. This would also solve the remaining 
back and forth issue with the YouTube progress bar and would even be 
compatible with non SIZED_STREAM capable clients.

-- 
Francois Gouget <fgouget at codeweavers.com>


More information about the Spice-devel mailing list