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

Kevin Pouget kpouget at redhat.com
Thu Aug 1 12:43:00 UTC 2019


On Wed, Jul 31, 2019 at 12:09 PM Kevin Pouget <kpouget at redhat.com> wrote:
>
> On Wed, Jul 31, 2019 at 11:50 AM Frediano Ziglio <fziglio at redhat.com> 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 ...
> > > ---
> > >  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 9858beb..6252e42 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;
> > >      }
> > > @@ -419,8 +419,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;
> > > @@ -431,20 +433,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;
> > >          }
> > > @@ -459,11 +447,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)
> > >
> > >      return true;
> > >  }
> >
> > I didn't test it but it makes perfectly sense.
> > On the other hand I'm wondering what will happen to the other
> > parameters. They will be "broadcasted" to all plugins.
> > For "framerate" is fine but what will happen if you specify
> > also properties (gst.prop) and encoder (gst.encoder) ?
>
> maybe the easiest is to say that "gst.XXX=YYY" applies to all the
> codecs, and "gst.CODEC.XXX=YYY" is only for one codec, with
> XXX=prop|encoder at the moment.

Hello,

I did the modifications below to allow passing codec-specific gst parameters:

> gst.codec=CODEC

> gst.prop | gst.CODEC.prop
> gst.encoder | gst.CODEC.prop
> framerate | gst.CODEC.framerate

regards,

Kevin

---
diff --git a/src/gst-plugin.cpp b/src/gst-plugin.cpp
index 5469647..4194485 100644
--- a/src/gst-plugin.cpp
+++ b/src/gst-plugin.cpp
@@ -102,7 +102,8 @@ class GstreamerPlugin final: public Plugin
 public:
     FrameCapture *CreateCapture() override;
     unsigned Rank() override;
-    void ParseOptions(const ConfigureOption *options,
SpiceVideoCodecType codec);
+    void ParseOptions(const ConfigureOption *options,
SpiceVideoCodecType codec,
+                      const std::string codec_name);
     SpiceVideoCodecType VideoCodecType() const override {
         return settings.codec;
     }
@@ -431,7 +432,8 @@ unsigned GstreamerPlugin::Rank()
     return SoftwareMin;
 }

-void GstreamerPlugin::ParseOptions(const ConfigureOption *options,
SpiceVideoCodecType codec)
+void GstreamerPlugin::ParseOptions(const ConfigureOption *options,
+                                   SpiceVideoCodecType codec, const
std::string codec_name)
 {
     settings.codec = codec;

@@ -439,15 +441,17 @@ void GstreamerPlugin::ParseOptions(const
ConfigureOption *options,  SpiceVideoCo
         const std::string name = options->name;
         const std::string value = options->value;

-        if (name == "framerate") {
+        if (name == "framerate" || name == "gst." + codec_name +
".framerate") {
             try {
                 settings.fps = std::stoi(value);
+
             } catch (const std::exception &e) {
-                throw std::runtime_error("Invalid value '" + value +
"' for option 'framerate'.");
+                throw std::runtime_error("Invalid value '" + value + '" "
+                                         "for option '" + name + "'.");
             }
-        } else if (name == "gst.encoder") {
+        } else if (name == "gst.encoder" || name == "gst." +
codec_name +".encoder") {
             settings.encoder = value;
-        } else if (name == "gst.prop") {
+        } else if (name == "gst.prop" || name == "gst." + codec_name
+ ".prop") {
             size_t pos = value.find('=');
             if (pos == 0 || pos >= value.size() - 1) {
                 gst_syslog(LOG_WARNING, "Property input is invalid
('%s' Ignored)", value.c_str());
@@ -488,7 +492,7 @@ SPICE_STREAMING_AGENT_PLUGIN(agent)
             }

             auto plugin = std::make_shared<GstreamerPlugin>();
-            plugin->ParseOptions(agent->Options(), codec_type);
+            plugin->ParseOptions(agent->Options(), codec_type, value);
             agent->Register(plugin);
         }
     }


More information about the Spice-devel mailing list