[Spice-devel] [RFC spice-streaming-agent 1/4] gst-plugin: allow the instantiation of multiple GST encoder plugins

Snir Sheriber ssheribe at redhat.com
Sun Aug 11 14:41:17 UTC 2019


Hi,



Tested, seems to work well! switching is smooth, if codec fails
it falls back to mjpeg (not very loudly), no default gstreamer
codec currently. As mentioned i find this feature useful :)

another comment below


On 8/6/19 6:34 PM, Kevin Pouget wrote:
> With this patch, spice-streaming-agent can be launched with multiple
> Gstreamer video codecs enabled:
>
>> spice-streaming-agent -c gst.codec=vp8 -c gst.codec=vp9 ...
> Signed-off-by: Kevin Pouget <kpouget at redhat.com>
> ---
>   src/gst-plugin.cpp | 50 ++++++++++++++++++++++++++++------------------
>   1 file changed, 31 insertions(+), 19 deletions(-)
>
> diff --git a/src/gst-plugin.cpp b/src/gst-plugin.cpp
> index 6415ac0..5469647 100644
> --- a/src/gst-plugin.cpp
> +++ b/src/gst-plugin.cpp
> @@ -102,7 +102,7 @@ class GstreamerPlugin final: public Plugin
>   public:
>       FrameCapture *CreateCapture() override;
>       unsigned Rank() override;
> -    void ParseOptions(const ConfigureOption *options);
> +    void ParseOptions(const ConfigureOption *options, SpiceVideoCodecType codec);
>       SpiceVideoCodecType VideoCodecType() const override {
>           return settings.codec;
>       }
> @@ -431,8 +431,10 @@ unsigned GstreamerPlugin::Rank()
>       return SoftwareMin;
>   }
>   
> -void GstreamerPlugin::ParseOptions(const ConfigureOption *options)
> +void GstreamerPlugin::ParseOptions(const ConfigureOption *options,  SpiceVideoCodecType codec)
>   {
> +    settings.codec = codec;
> +
>       for (; options->name; ++options) {
>           const std::string name = options->name;
>           const std::string value = options->value;
> @@ -443,20 +445,6 @@ void GstreamerPlugin::ParseOptions(const ConfigureOption *options)
>               } catch (const std::exception &e) {
>                   throw std::runtime_error("Invalid value '" + value + "' for option 'framerate'.");
>               }
> -        } else if (name == "gst.codec") {
> -            if (value == "h264") {
> -                settings.codec = SPICE_VIDEO_CODEC_TYPE_H264;
> -            } else if (value == "vp9") {
> -                settings.codec = SPICE_VIDEO_CODEC_TYPE_VP9;
> -            } else if (value == "vp8") {
> -                settings.codec = SPICE_VIDEO_CODEC_TYPE_VP8;
> -            } else if (value == "mjpeg") {
> -                settings.codec = SPICE_VIDEO_CODEC_TYPE_MJPEG;
> -            } else if (value == "h265") {
> -                settings.codec = SPICE_VIDEO_CODEC_TYPE_H265;
> -            } else {
> -                throw std::runtime_error("Invalid value '" + value + "' for option 'gst.codec'.");
> -            }
>           } else if (name == "gst.encoder") {
>               settings.encoder = value;
>           } else if (name == "gst.prop") {
> @@ -478,11 +466,35 @@ SPICE_STREAMING_AGENT_PLUGIN(agent)
>   {
>       gst_init(nullptr, nullptr);
>   
> -    auto plugin = std::make_shared<GstreamerPlugin>();
> +    auto options = agent->Options();
> +    for (; options->name; ++options) {
> +        const std::string name = options->name;
> +        const std::string value = options->value;
>   
> -    plugin->ParseOptions(agent->Options());
> +        if (name == "gst.codec") {
> +            SpiceVideoCodecType codec_type;
> +            if (value == "mjpeg") {
> +                codec_type = SPICE_VIDEO_CODEC_TYPE_MJPEG;
> +            } else if (value == "h264") {
> +                codec_type = SPICE_VIDEO_CODEC_TYPE_H264;
> +            } else if (value == "h265") {
> +                codec_type = SPICE_VIDEO_CODEC_TYPE_H265;
> +            } else if (value == "vp8") {
> +                codec_type = SPICE_VIDEO_CODEC_TYPE_VP8;
> +            } else if (value == "vp9") {
> +                codec_type = SPICE_VIDEO_CODEC_TYPE_VP9;
> +            } else {
> +                throw std::runtime_error("Invalid value '" + value + "' for option 'gst.codec'.");
> +            }
> +
> +            auto plugin = std::make_shared<GstreamerPlugin>();
> +            plugin->ParseOptions(agent->Options(), codec_type);
> +            agent->Register(plugin);
> +        }
> +    }
>   
> -    agent->Register(plugin);
> +    // no default value at the moment
> +    // (used to be h264, see GstreamerEncoderSettings::codec)

When moving to multiple codecs registration we may want to do
something more solid, for example checking for gstreamer's codec
availability before registering plugins or even trying to initialize the
pipeline before registration.

This will probably require more efforts, I'll try invest some time on 
that too.

Snir.


>   
>       return true;
>   }


More information about the Spice-devel mailing list