diff --git a/compositor/main.c b/compositor/main.c index 6ceb108e..5b78cbab 100644 --- a/compositor/main.c +++ b/compositor/main.c @@ -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; diff --git a/man/weston-drm.man b/man/weston-drm.man index 3cc490c0..488eef6e 100644 --- a/man/weston-drm.man +++ b/man/weston-drm.man @@ -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. . .\" *************************************************************** diff --git a/remoting/remoting-plugin.c b/remoting/remoting-plugin.c index 00d1ac77..7c9bbb11 100644 --- a/remoting/remoting-plugin.c +++ b/remoting/remoting-plugin.c @@ -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 diff --git a/remoting/remoting-plugin.h b/remoting/remoting-plugin.h index 8c82ac71..fdd429c5 100644 --- a/remoting/remoting-plugin.h +++ b/remoting/remoting-plugin.h @@ -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 *