remoting: make a gstreamer pipeline configurable
authorTomohito Esaki <etom@igel.co.jp>
Wed, 22 May 2019 03:21:32 +0000 (12:21 +0900)
committerDaniel Stone <daniel@fooishbar.org>
Tue, 9 Jul 2019 14:22:25 +0000 (14:22 +0000)
Allow a gstreamer pipeline to be configurable via an weston.ini. It is
necessary that source is appsrc, its name is "src", and sink name is
"sink" in pipeline. Also, remoting plugin ignore port and host
configuration if the gst-pipeline is specified.

compositor/main.c
man/weston-drm.man
remoting/remoting-plugin.c
remoting/remoting-plugin.h

index 6ceb108ee666864fb00123446aea59e008006e9e..5b78cbab8a59e848c947cb9f013b0f050c3e9972 100644 (file)
@@ -2196,6 +2196,7 @@ drm_backend_remoted_output_configure(struct weston_output *output,
        char *gbm_format = NULL;
        char *seat = NULL;
        char *host = NULL;
+       char *pipeline = NULL;
        int port, ret;
 
        ret = api->set_mode(output, modeline);
@@ -2220,21 +2221,23 @@ drm_backend_remoted_output_configure(struct weston_output *output,
        api->set_seat(output, seat);
        free(seat);
 
-       weston_config_section_get_string(section, "host", &host, NULL);
-       if (!host) {
-               weston_log("Cannot configure an output \"%s\". Invalid host\n",
-                          output->name);
-               return -1;
+       weston_config_section_get_string(section, "gst-pipeline", &pipeline,
+                                        NULL);
+       if (pipeline) {
+               api->set_gst_pipeline(output, pipeline);
+               free(pipeline);
+               return 0;
        }
-       api->set_host(output, host);
-       free(host);
 
+       weston_config_section_get_string(section, "host", &host, NULL);
        weston_config_section_get_int(section, "port", &port, 0);
-       if (port <= 0 || 65533 < port) {
-               weston_log("Cannot configure an output \"%s\". Invalid port\n",
-                          output->name);
-               return -1;
+       if (!host || port <= 0 || 65533 < port) {
+               weston_log("Cannot configure an output \"%s\". "
+                          "Need to specify gst-pipeline or "
+                          "host and port (1-65533).\n", output->name);
        }
+       api->set_host(output, host);
+       free(host);
        api->set_port(output, port);
 
        return 0;
index 3cc490c0502e0e6d38fc728d0f99d8ae1e071766..488eef6ef9d5faa9d5bfadd959521b069342abaf 100644 (file)
@@ -168,6 +168,12 @@ transmitted to.
 \fBport\fR=\fIport\fR
 Specify the port number to transmit the remote output to. Usable port range
 is 1-65533.
+.TP
+\fBgst-pipeline\fR=\fIpipeline\fR
+Specify the gstreamer pipeline. It is necessary that source is appsrc,
+its name is "src", and sink name is "sink" in
+.I pipeline\fR.
+Ignore port and host configuration if the gst-pipeline is specified.
 
 .
 .\" ***************************************************************
index 00d1ac7731b6e262c149d00a810ba9bd6f93be41..7c9bbb114258b57fdf0571133acc191bbcb7657f 100644 (file)
@@ -97,6 +97,7 @@ struct remoted_output {
 
        char *host;
        int port;
+       char *gst_pipeline;
        const struct remoted_output_support_gbm_format *format;
 
        struct weston_head *head;
@@ -180,26 +181,31 @@ remoting_gst_bus_sync_handler(GstBus *bus, GstMessage *message,
 static int
 remoting_gst_pipeline_init(struct remoted_output *output)
 {
-       char pipeline_str[1024];
        GstCaps *caps;
        GError *err = NULL;
        GstStateChangeReturn ret;
        struct weston_mode *mode = output->output->current_mode;
 
-       /* TODO: use encodebin instead of jpegenc */
-       snprintf(pipeline_str, sizeof(pipeline_str),
-                "rtpbin name=rtpbin "
-                "appsrc name=src ! videoconvert ! video/x-raw,format=I420 ! "
-                "jpegenc ! rtpjpegpay ! rtpbin.send_rtp_sink_0 "
-                "rtpbin.send_rtp_src_0 ! udpsink name=sink host=%s port=%d "
-                "rtpbin.send_rtcp_src_0 ! "
-                "udpsink host=%s port=%d sync=false async=false "
-                "udpsrc port=%d ! rtpbin.recv_rtcp_sink_0",
-                output->host, output->port, output->host, output->port + 1,
-                output->port + 2);
-       weston_log("GST pipeline: %s\n", pipeline_str);
-
-       output->pipeline = gst_parse_launch(pipeline_str, &err);
+       if (!output->gst_pipeline) {
+               char pipeline_str[1024];
+               /* TODO: use encodebin instead of jpegenc */
+               snprintf(pipeline_str, sizeof(pipeline_str),
+                        "rtpbin name=rtpbin "
+                        "appsrc name=src ! videoconvert ! "
+                        "video/x-raw,format=I420 ! jpegenc ! rtpjpegpay ! "
+                        "rtpbin.send_rtp_sink_0 "
+                        "rtpbin.send_rtp_src_0 ! "
+                        "udpsink name=sink host=%s port=%d "
+                        "rtpbin.send_rtcp_src_0 ! "
+                        "udpsink host=%s port=%d sync=false async=false "
+                        "udpsrc port=%d ! rtpbin.recv_rtcp_sink_0",
+                        output->host, output->port, output->host,
+                        output->port + 1, output->port + 2);
+               output->gst_pipeline = strdup(pipeline_str);
+       }
+       weston_log("GST pipeline: %s\n", output->gst_pipeline);
+
+       output->pipeline = gst_parse_launch(output->gst_pipeline, &err);
        if (!output->pipeline) {
                weston_log("Could not create gstreamer pipeline. Error: %s\n",
                           err->message);
@@ -214,6 +220,12 @@ remoting_gst_pipeline_init(struct remoted_output *output)
                goto err;
        }
 
+       /* check sink */
+       if (!gst_bin_get_by_name(GST_BIN(output->pipeline), "sink")) {
+               weston_log("Could not get sink from gstreamer pipeline\n");
+               goto err;
+       }
+
        caps = gst_caps_new_simple("video/x-raw",
                                   "format", G_TYPE_STRING,
                                             output->format->gst_format_string,
@@ -626,6 +638,8 @@ remoting_output_destroy(struct weston_output *output)
 
        if (remoted_output->host)
                free(remoted_output->host);
+       if (remoted_output->gst_pipeline)
+               free(remoted_output->gst_pipeline);
 
        wl_list_remove(&remoted_output->link);
        weston_head_release(remoted_output->head);
@@ -853,6 +867,20 @@ remoting_output_set_port(struct weston_output *output, int port)
                remoted_output->port = port;
 }
 
+static void
+remoting_output_set_gst_pipeline(struct weston_output *output,
+                                char *gst_pipeline)
+{
+       struct remoted_output *remoted_output = lookup_remoted_output(output);
+
+       if (!remoted_output)
+               return;
+
+       if (remoted_output->gst_pipeline)
+               free(remoted_output->gst_pipeline);
+       remoted_output->gst_pipeline = strdup(gst_pipeline);
+}
+
 static const struct weston_remoting_api remoting_api = {
        remoting_output_create,
        remoting_output_is_remoted,
@@ -861,6 +889,7 @@ static const struct weston_remoting_api remoting_api = {
        remoting_output_set_seat,
        remoting_output_set_host,
        remoting_output_set_port,
+       remoting_output_set_gst_pipeline,
 };
 
 WL_EXPORT int
index 8c82ac716599d950726f9d6892f6d7477e5dd816..fdd429c5ceed4a68d07344b6832ee8643c8f8065 100644 (file)
@@ -59,6 +59,10 @@ struct weston_remoting_api {
 
        /** Set the port number */
        void (*set_port)(struct weston_output *output, int port);
+
+       /** Set the pipeline for gstreamer */
+       void (*set_gst_pipeline)(struct weston_output *output,
+                                char *gst_pipeline);
 };
 
 static inline const struct weston_remoting_api *