mirror of
https://github.com/morgan9e/UxPlay
synced 2026-04-14 00:04:13 +09:00
add -vrtp option (requested by @tovrstra )
This commit is contained in:
19
README.html
19
README.html
@@ -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 <rest-of-pipeline></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 <n></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
|
||||
|
||||
16
README.md
16
README.md
@@ -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
|
||||
|
||||
19
README.txt
19
README.txt
@@ -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
|
||||
|
||||
@@ -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))){
|
||||
|
||||
@@ -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);
|
||||
|
||||
7
uxplay.1
7
uxplay.1
@@ -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.
|
||||
|
||||
17
uxplay.cpp
17
uxplay.cpp
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user