add -vrtp option (requested by @tovrstra )

This commit is contained in:
F. Duncanh
2025-09-26 01:10:41 -04:00
parent 151d4a7a3e
commit 2c3fcdcf8d
7 changed files with 101 additions and 32 deletions

View File

@@ -21,6 +21,13 @@ href="#bluetooth-le-beacon-setup">given below</a>. <strong>It is hoped
that users will submit Pull Requests contributing scripts for automating
beacon setup on all platforms. (Python may be an appropriate language
choice)</strong></p></li>
<li><p><strong>NEW on github</strong>: option
<code>-vrtp &lt;rest-of-pipeline&gt;</code> bypasses rendering by
UxPlay, and instead transmits rtp packets of decrypted h264 or h265
video to an external renderer (e.g. OBS Studio) at an address specified
in <code>rest-of-pipeline</code>. (Note: this is video only, an option
“-rtp” which muxes audio and video into a mpeg4 container still needs to
be created: Pull Requests welcomed).</p></li>
<li><p><strong>NEW on github</strong>: (for Linux/*BSD Desktop
Environments using D-Bus). New option <code>-scrsv &lt;n&gt;</code>
provides screensaver inhibition (e.g., to prevent screensaver function
@@ -1250,6 +1257,12 @@ display video), and only used to render audio, which will be AAC
lossily-compressed audio in mirror mode with unrendered video, and
superior-quality ALAC Apple Lossless audio in Airplay audio-only
mode.</p>
<p><strong>-vrtp <em>pipeline</em></strong>: forward rtp packets of
decrypted video to somewhere else, without rendering. Uses rtph264pay or
rtph265pay as appropriate: <em>pipeline</em> should start with any
rtph26xpay options (such as config_interval= or aggregate-mode =),
followed by a sending method: <em>e.g.</em>,
<code>"config-interval=1 ! udpsink host=127.0.0.1 port=5000</code>“.</p>
<p><strong>-v4l2</strong> Video settings for hardware h264 video
decoding in the GPU by Video4Linux2. Equivalent to
<code>-vd v4l2h264dec -vc v4l2convert</code>.</p>
@@ -1933,10 +1946,12 @@ an AppleTV6,2 with sourceVersion 380.20.1 (an AppleTV 4K 1st gen,
introduced 2017, running tvOS 12.2.1), so it does not seem to matter
what version UxPlay claims to be.</p>
<h1 id="changelog">Changelog</h1>
<p>xxxx 2025-08-11 Render Audio cover-art inside UxPlay with -ca option
<p>xxxx 2025-09-25 Render Audio cover-art inside UxPlay with -ca option
(no file specified). (D-Bus based) option -scrsv <n> to inhibit
screensaver while UxPlay is running (Linux/*BSD only). Add support for
Service Discovery using a Bluetooth LE beacon.</p>
Service Discovery using a Bluetooth LE beacon. Add -vrtp option for
forwarding decrypted h264/5 video to an external renderer (e.g., OBS
Studio)</p>
<p>1.72.2 2025-07-07 Fix bug (typo) in DNS_SD advertisement introduced
with -pw option. Update llhttp to v 9.3.0</p>
<p>1.72.1 2025-06-06 minor update: fix regression in -reg option; add

View File

@@ -10,6 +10,12 @@
__It is hoped that users will submit Pull Requests contributing scripts for automating beacon setup on all platforms.
(Python may be an appropriate language choice)__
- **NEW on github**: option `-vrtp <rest-of-pipeline>` bypasses rendering by UxPlay, and instead
transmits rtp packets of decrypted h264 or h265 video to
an external renderer (e.g. OBS Studio) at an address specified in `rest-of-pipeline`.
(Note: this is video only, an option "-rtp" which muxes audio and video into a mpeg4 container still needs to be created:
Pull Requests welcomed).
- **NEW on github**: (for Linux/*BSD Desktop Environments using D-Bus). New option `-scrsv <n>` provides screensaver inhibition (e.g., to
prevent screensaver function while watching mirrored videos without keyboard or mouse
activity): n = 0 (off) n=1 (on during video activity) n=2 (always on while UxPlay is running).
@@ -1252,6 +1258,11 @@ video), and only used to render audio, which will be AAC
lossily-compressed audio in mirror mode with unrendered video, and
superior-quality ALAC Apple Lossless audio in Airplay audio-only mode.
**-vrtp *pipeline***: forward rtp packets of decrypted video to somewhere else, without rendering.
Uses rtph264pay or rtph265pay as appropriate: *pipeline* should start with any
rtph26xpay options (such as config_interval= or aggregate-mode =), followed by
a sending method: *e.g.*, `"config-interval=1 ! udpsink host=127.0.0.1 port=5000`".
**-v4l2** Video settings for hardware h264 video decoding in the GPU by
Video4Linux2. Equivalent to `-vd v4l2h264dec -vc v4l2convert`.
@@ -1957,10 +1968,11 @@ introduced 2017, running tvOS 12.2.1), so it does not seem to matter
what version UxPlay claims to be.
# Changelog
xxxx 2025-08-11 Render Audio cover-art inside UxPlay with -ca option (no file
xxxx 2025-09-25 Render Audio cover-art inside UxPlay with -ca option (no file
specified). (D-Bus based) option -scrsv <n> to inhibit screensaver while UxPlay
is running (Linux/*BSD only). Add support for Service Discovery using a
Bluetooth LE beacon.
Bluetooth LE beacon. Add -vrtp option for forwarding decrypted h264/5 video
to an external renderer (e.g., OBS Studio)
1.72.2 2025-07-07 Fix bug (typo) in DNS_SD advertisement introduced with -pw
option. Update llhttp to v 9.3.0

View File

@@ -16,6 +16,13 @@
setup on all platforms. (Python may be an appropriate language
choice)**
- **NEW on github**: option `-vrtp <rest-of-pipeline>` bypasses
rendering by UxPlay, and instead transmits rtp packets of decrypted
h264 or h265 video to an external renderer (e.g. OBS Studio) at an
address specified in `rest-of-pipeline`. (Note: this is video only,
an option "-rtp" which muxes audio and video into a mpeg4 container
still needs to be created: Pull Requests welcomed).
- **NEW on github**: (for Linux/\*BSD Desktop Environments using
D-Bus). New option `-scrsv <n>` provides screensaver inhibition
(e.g., to prevent screensaver function while watching mirrored
@@ -1276,6 +1283,12 @@ video), and only used to render audio, which will be AAC
lossily-compressed audio in mirror mode with unrendered video, and
superior-quality ALAC Apple Lossless audio in Airplay audio-only mode.
**-vrtp *pipeline***: forward rtp packets of decrypted video to
somewhere else, without rendering. Uses rtph264pay or rtph265pay as
appropriate: *pipeline* should start with any rtph26xpay options (such
as config_interval= or aggregate-mode =), followed by a sending method:
*e.g.*, `"config-interval=1 ! udpsink host=127.0.0.1 port=5000`".
**-v4l2** Video settings for hardware h264 video decoding in the GPU by
Video4Linux2. Equivalent to `-vd v4l2h264dec -vc v4l2convert`.
@@ -2006,10 +2019,12 @@ what version UxPlay claims to be.
# Changelog
xxxx 2025-08-11 Render Audio cover-art inside UxPlay with -ca option (no
xxxx 2025-09-25 Render Audio cover-art inside UxPlay with -ca option (no
file specified). (D-Bus based) option -scrsv `<n>`{=html} to inhibit
screensaver while UxPlay is running (Linux/\*BSD only). Add support for
Service Discovery using a Bluetooth LE beacon.
Service Discovery using a Bluetooth LE beacon. Add -vrtp option for
forwarding decrypted h264/5 video to an external renderer (e.g., OBS
Studio)
1.72.2 2025-07-07 Fix bug (typo) in DNS_SD advertisement introduced with
-pw option. Update llhttp to v 9.3.0

View File

@@ -222,11 +222,12 @@ GstElement *make_video_sink(const char *videosink, const char *videosink_options
return video_sink;
}
void video_renderer_init(logger_t *render_logger, const char *server_name, videoflip_t videoflip[2], const char *parser,
void video_renderer_init(logger_t *render_logger, const char *server_name, videoflip_t videoflip[2], const char *parser, const char * rtp_pipeline,
const char *decoder, const char *converter, const char *videosink, const char *videosink_options,
bool initial_fullscreen, bool video_sync, bool h265_support, bool coverart_support, guint playbin_version, const char *uri) {
GError *error = NULL;
GstCaps *caps = NULL;
bool rtp = (bool) strlen(rtp_pipeline);
hls_video = (uri != NULL);
/* videosink choices that are auto */
auto_videosink = (strstr(videosink, "autovideosink") || strstr(videosink, "fpsdisplaysink"));
@@ -332,30 +333,36 @@ void video_renderer_init(logger_t *render_logger, const char *server_name, video
g_string_append(launch, "queue ! ");
g_string_append(launch, parser);
g_string_append(launch, " ! ");
g_string_append(launch, decoder);
if (!rtp) {
g_string_append(launch, decoder);
} else {
g_string_append(launch, "rtph264pay ");
g_string_append(launch, rtp_pipeline);
}
}
g_string_append(launch, " ! ");
append_videoflip(launch, &videoflip[0], &videoflip[1]);
g_string_append(launch, converter);
g_string_append(launch, " ! ");
g_string_append(launch, "videoscale ! ");
if (jpeg_pipeline) {
g_string_append(launch, " imagefreeze allow-replace=TRUE ! ");
if (!rtp || jpeg_pipeline) {
g_string_append(launch, " ! ");
append_videoflip(launch, &videoflip[0], &videoflip[1]);
g_string_append(launch, converter);
g_string_append(launch, " ! ");
g_string_append(launch, "videoscale ! ");
if (jpeg_pipeline) {
g_string_append(launch, " imagefreeze allow-replace=TRUE ! ");
}
g_string_append(launch, videosink);
g_string_append(launch, " name=");
g_string_append(launch, videosink);
g_string_append(launch, "_");
g_string_append(launch, renderer_type[i]->codec);
g_string_append(launch, videosink_options);
if (video_sync && !jpeg_pipeline) {
g_string_append(launch, " sync=true");
sync = true;
} else {
g_string_append(launch, " sync=false");
sync = false;
}
}
g_string_append(launch, videosink);
g_string_append(launch, " name=");
g_string_append(launch, videosink);
g_string_append(launch, "_");
g_string_append(launch, renderer_type[i]->codec);
g_string_append(launch, videosink_options);
if (video_sync && !jpeg_pipeline) {
g_string_append(launch, " sync=true");
sync = true;
} else {
g_string_append(launch, " sync=false");
sync = false;
}
if (!strcmp(renderer_type[i]->codec, h264)) {
char *pos = launch->str;
while ((pos = strstr(pos,h265))){

View File

@@ -47,7 +47,7 @@ typedef enum videoflip_e {
typedef struct video_renderer_s video_renderer_t;
void video_renderer_init (logger_t *logger, const char *server_name, videoflip_t videoflip[2], const char *parser,
void video_renderer_init (logger_t *logger, const char *server_name, videoflip_t videoflip[2], const char *parser, const char *rtp_pipeline,
const char *decoder, const char *converter, const char *videosink, const char *videosink_options,
bool initial_fullscreen, bool video_sync, bool h265_support, bool coverart_support,
guint playbin_version, const char *uri);

View File

@@ -98,6 +98,13 @@ UxPlay 1.72: An open\-source AirPlay mirroring (+ audio streaming) server:
.TP
\fB\-vs\fR 0 Streamed audio only, with no video display window.
.TP
\fB\-vrtp\fI pl\fR Use rtph26[4,5]pay to send decoded video elsewhere: "pl"
.IP
is the remaining pipeline, starting with rtph26*pay options:
.IP
e.g. "config-interval=1 ! udpsink host=127.0.0.1 port=5000"
.PP
.TP
\fB\-v4l2\fR Use Video4Linux2 for GPU hardware h264 video decoding.
.TP
\fB\-bt709\fR Sometimes needed for Raspberry Pi models using Video4Linux2.

View File

@@ -190,6 +190,8 @@ static uint32_t rtptime_coverart_expired = 0;
static std::string artist;
static std::string coverart_artist;
static std::string ble_filename = "";
static std::string rtp_pipeline = "";
//Support for D-Bus-based screensaver inhibition (org.freedesktop.ScreenSaver)
static unsigned int scrsv;
@@ -879,6 +881,9 @@ static void print_info (char *name) {
printf(" gtksink,waylandsink,kmssink,fbdevsink,osxvideosink,\n");
printf(" d3d11videosink,d3v12videosink, etc.\n");
printf("-vs 0 Streamed audio only, with no video display window\n");
printf("-vrtp pl Use rtph26[4,5]pay to send decoded video elsewhere: \"pl\"\n");
printf(" is the remaining pipeline, starting with rtph26*pay options:\n");
printf(" e.g. \"config-interval=1 ! udpsink host=127.0.0.1 port=5000\"\n");
printf("-v4l2 Use Video4Linux2 for GPU hardware h264 decoding\n");
printf("-bt709 Sometimes needed for Raspberry Pi models using Video4Linux2 \n");
printf("-srgb Display \"Full range\" [0-255] color, not \"Limited Range\"[16-235]\n");
@@ -1297,6 +1302,14 @@ static void parse_arguments (int argc, char *argv[]) {
fprintf(stderr, "invalid \"-reset %s\"; -reset n must have n >= 0, default n = %d seconds\n", argv[i], MISSED_FEEDBACK_LIMIT);
exit(1);
}
} else if (arg == "-vrtp") {
if (!option_has_value(i, argc, arg, argv[i+1])) {
fprintf(stderr,"option \"-vrtp\" must be followed by a pipeline for sending the video stream:\n"
"e.g., \"<rtph26[4,5]pay options> ! udpsink host=127.0.0.1 port -= 5000\"\n");
exit(1);
}
rtp_pipeline.erase();
rtp_pipeline.append(argv[++i]);
} else if (arg == "-vdmp") {
dump_video = true;
if (i < argc - 1 && *argv[i+1] != '-') {
@@ -2817,7 +2830,7 @@ int main (int argc, char *argv[]) {
LOGI("audio_disabled");
}
if (use_video) {
video_renderer_init(render_logger, server_name.c_str(), videoflip, video_parser.c_str(),
video_renderer_init(render_logger, server_name.c_str(), videoflip, video_parser.c_str(), rtp_pipeline.c_str(),
video_decoder.c_str(), video_converter.c_str(), videosink.c_str(),
videosink_options.c_str(), fullscreen, video_sync, h265_support,
render_coverart, playbin_version, NULL);
@@ -2914,7 +2927,7 @@ int main (int argc, char *argv[]) {
raop_remove_known_connections(raop);
}
const char *uri = (url.empty() ? NULL : url.c_str());
video_renderer_init(render_logger, server_name.c_str(), videoflip, video_parser.c_str(),
video_renderer_init(render_logger, server_name.c_str(), videoflip, video_parser.c_str(),rtp_pipeline.c_str(),
video_decoder.c_str(), video_converter.c_str(), videosink.c_str(),
videosink_options.c_str(), fullscreen, video_sync, h265_support,
render_coverart, playbin_version, uri);