Commit f709d220 authored by Tomohito Esaki's avatar Tomohito Esaki

Add remoting plugin for output streaming

Remoting plugin support streaming image of virtual output on drm-backend
to remote output. By appending remote-output section in weston.ini,
weston loads remoting plugin module and creates virtual outputs via
remoting plugin. The mode, host, and port properties are configurable in
remote-output section.

This plugin send motion jpeg images to client via RTP using gstreamer.
Client can receive by using following pipeline of gst-launch.

gst-launch-1.0 rtpbin name=rtpbin \
   udpsrc caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,
		encoding-name=JPEG,payload=26" port=[PORTNUMBER] !
          rtpbin.recv_rtp_sink_0 \
   rtpbin. ! rtpjpegdepay ! jpegdec ! autovideosink \
   udpsrc port=[PORTNUMBER+1] ! rtpbin.recv_rtcp_sink_0 \
   rtpbin.send_rtcp_src_0 !
          udpsink port=[PORTNUMBER+2] sync=false async=false

where, PORTNUMBER is specified in weston.ini.
Signed-off-by: Tomohito Esaki's avatarTomohito Esaki <etom@igel.co.jp>
parent f59dc111
......@@ -402,6 +402,23 @@ drm_backend_la_LIBADD += $(LIBVA_LIBS)
drm_backend_la_LDFLAGS += -pthread
drm_backend_la_CFLAGS += $(LIBVA_CFLAGS)
endif
# remoting
if ENABLE_REMOTING
libweston_module_LTLIBRARIES += remoting-plugin.la
remoting_plugin_la_LDFLAGS = -module -avoid-version
remoting_plugin_la_LIBADD = \
$(COMPOSITOR_LIBS) \
$(REMOTING_GST_LIBS)
remoting_plugin_la_CFLAGS = \
$(COMPOSITOR_CFLAGS) \
$(REMOTING_GST_CFLAGS) \
$(AM_CFLAGS)
remoting_plugin_la_SOURCES = \
remoting/remoting-plugin.c \
remoting/remoting-plugin.h
endif
endif
if ENABLE_WAYLAND_COMPOSITOR
......
......@@ -61,6 +61,7 @@
#include "compositor-wayland.h"
#include "windowed-output-api.h"
#include "weston-debug.h"
#include "../remoting/remoting-plugin.h"
#define WINDOW_TITLE "Weston Compositor"
......@@ -1973,6 +1974,154 @@ drm_heads_changed(struct wl_listener *listener, void *arg)
wet->init_failed = true;
}
static int
drm_backend_remoted_output_configure(struct weston_output *output,
struct weston_config_section *section,
char *modeline,
const struct weston_remoting_api *api)
{
char *gbm_format = NULL;
char *seat = NULL;
char *host = NULL;
int port, ret;
ret = api->set_mode(output, modeline);
if (ret < 0) {
weston_log("Cannot configure an output \"%s\" using "
"weston_remoting_api. Invalid mode\n",
output->name);
return -1;
}
wet_output_set_scale(output, section, 1, 0);
wet_output_set_transform(output, section, WL_OUTPUT_TRANSFORM_NORMAL,
UINT32_MAX);
weston_config_section_get_string(section, "gbm-format", &gbm_format,
NULL);
api->set_gbm_format(output, gbm_format);
free(gbm_format);
weston_config_section_get_string(section, "seat", &seat, "");
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;
}
api->set_host(output, host);
free(host);
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;
}
api->set_port(output, port);
return 0;
}
static void
remoted_output_init(struct weston_compositor *c,
struct weston_config_section *section,
const struct weston_remoting_api *api)
{
struct weston_output *output = NULL;
char *output_name, *modeline = NULL;
int ret;
weston_config_section_get_string(section, "name", &output_name,
NULL);
if (!output_name)
return;
weston_config_section_get_string(section, "mode", &modeline, "off");
if (strcmp(modeline, "off") == 0)
goto err;
output = api->create_output(c, output_name);
if (!output) {
weston_log("Cannot create remoted output \"%s\".\n",
output_name);
goto err;
}
ret = drm_backend_remoted_output_configure(output, section, modeline,
api);
if (ret < 0) {
weston_log("Cannot configure remoted output \"%s\".\n",
output_name);
goto err;
}
if (weston_output_enable(output) < 0) {
weston_log("Enabling remoted output \"%s\" failed.\n",
output_name);
goto err;
}
free(modeline);
free(output_name);
weston_log("remoted output '%s' enabled\n", output->name);
return;
err:
free(modeline);
free(output_name);
if (output)
weston_output_destroy(output);
}
static void
load_remoting(struct weston_compositor *c, struct weston_config *wc)
{
const struct weston_remoting_api *api = NULL;
int (*module_init)(struct weston_compositor *ec);
struct weston_config_section *section = NULL;
const char *section_name;
/* read remote-output section in weston.ini */
while (weston_config_next_section(wc, &section, &section_name)) {
if (strcmp(section_name, "remote-output"))
continue;
if (!api) {
char *module_name;
struct weston_config_section *core_section =
weston_config_get_section(wc, "core", NULL,
NULL);
weston_config_section_get_string(core_section,
"remoting",
&module_name,
"remoting-plugin.so");
module_init = weston_load_module(module_name,
"weston_module_init");
free(module_name);
if (!module_init) {
weston_log("Can't load remoting-plugin\n");
return;
}
if (module_init(c) < 0) {
weston_log("Remoting-plugin init failed\n");
return;
}
api = weston_remoting_get_api(c);
if (!api)
return;
}
remoted_output_init(c, section, api);
}
}
static int
load_drm_backend(struct weston_compositor *c,
int *argc, char **argv, struct weston_config *wc)
......@@ -2015,6 +2164,9 @@ load_drm_backend(struct weston_compositor *c,
ret = weston_compositor_load_backend(c, WESTON_BACKEND_DRM,
&config.base);
/* remoting */
load_remoting(c, wc);
free(config.gbm_format);
free(config.seat_id);
......
......@@ -226,6 +226,16 @@ if test x$enable_drm_compositor = xyes; then
[AC_MSG_WARN([GBM does not support dmabuf import, will omit that capability])])
fi
AC_ARG_ENABLE(remoting, [ --enable-remoting],,
enable_remoting=no)
AM_CONDITIONAL(ENABLE_REMOTING, test x$enable_remoting = xyes)
if test x$enable_remoting = xyes; then
if test x$enable_drm_compositor != xyes; then
AC_MSG_WARN([The remoting-plugin.so module requires the DRM backend.])
fi
PKG_CHECK_MODULES(REMOTING_GST, [gstreamer-1.0 gstreamer-allocators-1.0 gstreamer-app-1.0 gstreamer-video-1.0])
fi
PKG_CHECK_MODULES(LIBINPUT_BACKEND, [libinput >= 0.8.0])
PKG_CHECK_MODULES(COMPOSITOR, [$COMPOSITOR_MODULES])
......@@ -727,6 +737,7 @@ AC_MSG_RESULT([
systemd notify support ${enable_systemd_notify}
DRM Compositor ${enable_drm_compositor}
Remoting ${enable_remoting}
X11 Compositor ${enable_x11_compositor}
Wayland Compositor ${enable_wayland_compositor}
Headless Compositor ${enable_headless_compositor}
......
#!/bin/bash
# Copyright © 2018 Renesas Electronics Corp.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice (including the
# next paragraph) shall be included in all copies or substantial
# portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Authors: IGEL Co., Ltd.
# By using this script, client can receive remoted output via gstreamer.
# Usage:
# remoting-client-receive.bash <PORT NUMBER>
gst-launch-1.0 rtpbin name=rtpbin \
udpsrc caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=JPEG,payload=26" port=$1 ! \
rtpbin.recv_rtp_sink_0 \
rtpbin. ! rtpjpegdepay ! jpegdec ! autovideosink \
udpsrc port=$(($1 + 1)) ! rtpbin.recv_rtcp_sink_0 \
rtpbin.send_rtcp_src_0 ! \
udpsink port=$(($1 + 2)) sync=false async=false
......@@ -45,6 +45,13 @@ including
can run on other VTs. On switching back to Weston's VT, input devices
and DRM master are re-acquired through the parent process
.BR weston-launch .
The DRM backend also supports virtual outputs that are transmitted over
an RTP session as a series of JPEG images (RTP payload type 26) to a remote
client. Virtual outputs are configured in the
.BR remote-output
section of
.BR weston.ini.
.
.\" ***************************************************************
.SH CONFIGURATION
......@@ -138,6 +145,30 @@ Defaults to false. Note that
When a connector is disconnected, there is no EDID information to provide
a list of video modes. Therefore a forced output should also have a
detailed mode line specified.
.SS Section remote-output
.TP
\fBname\fR=\fIname\fR
Specify unique name for the output.
.TP
\fBmode\fR=\fImode\fR
Specify the video mode for the output. The argument
.I mode
is a resolution setting, such as:
.TP
\fBmode\fR=\fIwidthxheight\fR
.TP
\fBmode\fR=\fIwidthxheight@refresh_rate
If refresh_rate is not specified it will default to a 60Hz.
.TP
\fBhost\fR=\fIhost\fR
Specify the host name or IP Address that the remote output will be
transmitted to.
.TP
\fBport\fR=\fIport\fR
Specify the port number to transmit the remote output to. Usable port range
is 1-65533.
.
.\" ***************************************************************
.SH OPTIONS
......
......@@ -189,6 +189,19 @@ useful for debugging a crash on start-up when it would be inconvenient to
launch weston directly from a debugger. Boolean, defaults to
.BR false .
There is also a command line option to do the same.
.TP 7
.BI "remoting="remoting-plugin.so
specifies a plugin for remote output to load (string). This can be used to load
your own implemented remoting plugin or one with Weston as default. Available
remoting plugins in the
.IR "__libweston_modules_dir__"
directroy are:
.PP
.RS 10
.nf
.BR remoting-plugin.so
.fi
.RE
.SH "LIBINPUT SECTION"
The
......
Remoting plugin for Weston
The Remoting plugin creates a streaming image of a virtual output and transmits
it to a remote host. It is currently only supported on the drm-backend. Virtual
outputs are created and configured by adding a remote-output section to
weston.ini. See man weston-drm(7) for configuration details. This plugin is
loaded automatically if any remote-output sections are present.
This plugin sends motion jpeg images to a client via RTP using gstreamer, and
so requires gstreamer-1.0. This plugin starts sending images immediately when
weston is run, and keeps sending them until weston shuts down. The image stream
can be received by any appropriately configured RTP client, but a sample
gstreamer RTP client script can be found at doc/remoting-client-receive.bash.
Script usage:
remoting-client-receive.bash <PORT NUMBER>
How to compile
---------------
Set --enable-remoting=true when configuring weston. The remoting-plugin.so
module is created and installed in the libweston path.
How to configure weston.ini
----------------------------
See man weston-drm(7).
This diff is collapsed.
/*
* Copyright © 2018 Renesas Electronics Corp.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: IGEL Co., Ltd.
*/
#ifndef REMOTING_PLUGIN_H
#define REMOTING_PLUGIN_H
#include "compositor.h"
#include "plugin-registry.h"
#define WESTON_REMOTING_API_NAME "weston_remoting_api_v1"
struct weston_remoting_api {
/** Create remoted outputs
*
* Returns 0 on success, -1 on failure.
*/
struct weston_output *(*create_output)(struct weston_compositor *c,
char *name);
/** Check if output is remoted */
bool (*is_remoted_output)(struct weston_output *output);
/** Set mode */
int (*set_mode)(struct weston_output *output, const char *modeline);
/** Set gbm format */
void (*set_gbm_format)(struct weston_output *output,
const char *gbm_format);
/** Set seat */
void (*set_seat)(struct weston_output *output, const char *seat);
/** Set the destination Host(IP Address) */
void (*set_host)(struct weston_output *output, char *ip);
/** Set the port number */
void (*set_port)(struct weston_output *output, int port);
};
static inline const struct weston_remoting_api *
weston_remoting_get_api(struct weston_compositor *compositor)
{
const void *api;
api = weston_plugin_api_get(compositor, WESTON_REMOTING_API_NAME,
sizeof(struct weston_remoting_api));
return (const struct weston_remoting_api *)api;
}
#endif /* REMOTING_PLUGIN_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment