[Spice-devel] [PATCH spice 6/11] server: Add VP8 support, a video codec preference list and compatibility checks with the Spice client.
Francois Gouget
fgouget at codeweavers.com
Tue May 26 12:26:35 PDT 2015
On Tue, 19 May 2015, Marc-André Lureau wrote:
[...]
> > + /* Set the encoder initial bit rate, and ask for a low latency */
> > + adjust_bit_rate(encoder);
> > + g_object_set(G_OBJECT(encoder->gstenc), "bitrate", encoder->bit_rate, NULL);
> > + g_object_set(G_OBJECT(encoder->gstenc), "max-latency", 0, NULL);
> > + g_object_set(G_OBJECT(encoder->gstenc), "max-keyframe-distance", 0, NULL);
> > + g_object_set(G_OBJECT(encoder->gstenc), "lag-in-frames", 0, NULL);
> > +
>
> Those paremeters do not exist with all encoders, notably ffenc_mjpeg.
I'll tweak it so we only set the properties supported by the current
encoder.
> We could rather use or define encodebin profiles.
See discussion in the previous email.
[...]
> > + if (encoder->base.codec_type == SPICE_VIDEO_CODEC_TYPE_VP8) {
> > + /* vp8enc gets confused if we try to reconfigure the pipeline */
> > reset_pipeline(encoder);
>
> You'll easily reach this condition with CAP_SIZED_STREAM streams.
It's ok. reset_pipeline() frees the current pipeline, causing
gst_encoder_encode_frame() to call construct_pipeline() as if this was
the stream's first frame.
[...]
> > /* The GStreamer buffer timestamps and framerate are irrelevant and would
> > * be hard to set right because they can arrive a bit irregularly
> > */
> > - GST_BUFFER_TIMESTAMP(buffer) = GST_CLOCK_TIME_NONE;
> > - GST_BUFFER_DURATION(buffer) = GST_CLOCK_TIME_NONE;
> > + if (encoder->base.codec_type == SPICE_VIDEO_CODEC_TYPE_VP8)
> > + {
> > + /* FIXME: Maybe try drop-frame = 0 instead? */
> > + GST_BUFFER_TIMESTAMP(buffer) = frame_time;
> > + GST_BUFFER_DURATION(buffer) = 1;
> > + }
> > + else
> > + {
> > + GST_BUFFER_TIMESTAMP(buffer) = GST_CLOCK_TIME_NONE;
> > + GST_BUFFER_DURATION(buffer) = GST_CLOCK_TIME_NONE;
> > + }
>
> What is this supposed to change? Did you consider appsrc do-timestamp
> instead?
It's a hack to get both the mjpeg end vp8 encoders working.
Using 'appsrc do-timestamp=1' works for the mjpeg encoder but causes us
to block indefinitely in gst_app_sink_pull_buffer() for the vp8 encoder
(independently of is-live), for an unknown reason.
My suspicion is that the frame gets dropped, presumably by vp8enc
itself, maybe due to pipeline latency issues.
I'm also not sure yet of what the best approach is for timestamping and
setting the framerate in the appsrc caps and their impact on the
bitrate.
One option is to advertise the outgoing framerate, the target bitrate
and use do-timestamping. The outgoing framerate, e.g. 10fps, may be
lower than the source framerate, e.g. 24 fps, which implies dropping
frames before passing them off to the pipeline. This means some frames
will be less than 1/10th second apart and, if I remember correctly,
this causes the pipeline to drop them which is not what we want (and
again causes a freeze in gst_app_sink_pull_buffer()).
Another option is to set the bitrate and framerate to get the desired
compressed buffer size. Then the stream's bitrate can be further reduced
by controlling the outgoing frame rate. In this case I'm not sure using
real timestamps makes sense.
> > @@ -364,13 +382,13 @@ static int gst_encoder_encode_frame(GstEncoder
> > *encoder,
> > encoder->spice_format = bitmap->format;
> > encoder->width = width;
> > encoder->height = height;
> > - if (encoder->pipeline && !reconfigure_pipeline(encoder))
> > - return VIDEO_ENCODER_FRAME_UNSUPPORTED;
> > + if (encoder->pipeline)
> > + reconfigure_pipeline(encoder);
>
> Why this change?
reconfigure_pipeline() used to return false if it failed to reconfigure
the pipeline. With the old code this would cause us to return
FRAME_UNSUPPORTED. But in fact in such a case the existing pipeline has
been freed and all we need to do is to rebuild it from scratch which is
what we already do a few lines down.
This should maybe have been part of patch 5 though
reconfigure_pipeline() does not fail with ffenc_mjpeg.
> > + agent->video_encoder = red_display_create_video_encoder(dcc, initial_bit_rate, &video_cbs, agent);
> > } else {
> > - agent->video_encoder = create_video_encoder(0, NULL, NULL);
> > + agent->video_encoder = red_display_create_video_encoder(dcc, 0, NULL, NULL);
> > }
> > + /* FIXME: We may have failed to create a video encoder which will cause
> > + * a crash!
> > + */
>
> You may disable video streaming in this case? (worker->streaming_video ==
> STREAM_VIDEO_OFF)
The administrator could certainly set this option.
But as for gracefully handling this failure without configuration, as
far as I can tell, by the time red_display_create_stream() fails it's
too late to set streaming_video.
--
Francois Gouget <fgouget at codeweavers.com>
More information about the Spice-devel
mailing list