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

Submitted by Kevin Pouget on Aug. 6, 2019, 3:34 p.m.

Details

Message ID 20190806153453.20616-5-kpouget@redhat.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Kevin Pouget Aug. 6, 2019, 3:34 p.m.
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@redhat.com>
---
 src/gst-plugin.cpp | 50 ++++++++++++++++++++++++++++------------------
 1 file changed, 31 insertions(+), 19 deletions(-)

Patch hide | download patch | download mbox

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)
 
     return true;
 }

Comments

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@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;
>   }