UxPlay 1.38 added option -as to choose GStreamer audiosink

This commit is contained in:
fduncanh
2021-10-08 04:09:50 -04:00
parent 03ae968188
commit 3ee23bad57
5 changed files with 48 additions and 19 deletions

View File

@@ -1,4 +1,4 @@
# UxPlay 1.37
# UxPlay 1.38
This project is a GPLv3 unix AirPlay server which now also works on macOS.
Its main use is to act like an AppleTV for screen-mirroring (with audio) of iOS/macOS clients
@@ -21,7 +21,7 @@ If the client streams audio using AirPlay as opposed to AirPlay screen-mirrorin
input into the GStreamer audio-rendering pipeline, but does not get rendered into audio output. If someone can adapt the GStreamer audio
pipeline to also render these Airplay audio streams, such an enhancement of UxPlay would be welcome as a Pull Request!_
UxPlay 1.37 is based on https://github.com/FD-/RPiPlay, with GStreamer integration from
UxPlay 1.38 is based on https://github.com/FD-/RPiPlay, with GStreamer integration from
https://github.com/antimof/UxPlay.
(UxPlay only uses GStreamer, and does not contain the alternative Raspberry-Pi-specific
audio and video renderers also found in RPiPlay.)
@@ -198,6 +198,11 @@ plugin for Intel graphics is *NOT* installed (**uninstall it** if it is installe
"-vs ximagesink" or "-vs xvimagesink", to see if this fixes the problem, or "-vs vaapisink" to see if this
reproduces the problem.)
You can try to fix audio problems by using the "-as _audiosink_" option to choose the GStreamer audiosink , rather than
have autoaudiosink pick one for you. The command "gst_inspect-1.0 | grep Sink | grep Audio" " will show you which audiosinks and videosinks are
available on your system. (Replace "Audio" by "Video" to see videosinks). Common audiosinks are pulsesink, alsasink, osssink, oss4sink,
and osxaudiosink (macOS).
If you ran cmake with "-DZOOMFIX=ON", check if the problem is still there without ZOOMFIX.
ZOOMFIX is only applied to the default videosink choice ("autovideosink") and the two X11 videosinks
"ximagesink" and "xvimagesink". ZOOMFIX is only designed for these last two; if
@@ -269,7 +274,7 @@ which will not work if a firewall is running.
attempt to run two instances of uxplay on the same computer.)
On macOS, random MAC addresses are always used.
**-a** disable audio, leaving only the video playing.
Also: image transforms that had been added to RPiPlay have been ported to UxPlay:
@@ -290,6 +295,14 @@ Also: image transforms that had been added to RPiPlay have been ported to UxPlay
**-vs 0** suppresses display of streamed video, but plays streamed audio. (The client's screen
is still mirrored at a reduced rate of 1 frame per second, but is not rendered or displayed.)
**-as _audiosink_** chooses the GStreamer audiosink, instead of letting
autoaudiosink pick it for you. Some audiosink choices are: pulsesink, alsasink,
osssink, oss4sink, and osxaudiosink (for macOS). Using quotes
"..." might allow some parameters to be included with the audiosink name.
(Some choices of audiosink might not work on your system.)
**-as 0** or **-a** suppresses playing of streamed audio, but displays streamed video.
**-t _timeout_** will cause the server to relaunch (without stopping uxplay) if no connections
have been present during the previous _timeout_ seconds. (You may wish to use this because the Server may not be
visible to new Clients that were inactive when the Server was launched, and an idle Bonjour
@@ -302,6 +315,8 @@ Also: image transforms that had been added to RPiPlay have been ported to UxPlay
# ChangeLog
1.38 2021-10-8 Add -as _audiosink_ option to allow user to choose the GStreamer audiosink.
1.37 2021-09-29 Append "@hostname" to AirPlay Server name, where "hostname" is the name of the
server running uxplay (reworked change in 1.36).
@@ -330,7 +345,7 @@ This involved crypto updates, replacement
of the included plist library by the system-installed version, and a change
over to a library llhttp for http parsing.
2. Added the -s, -o -p, -m, -r, -f, -fps -vs and -t options.
2. Added the -s, -o -p, -m, -r, -f, -fps -vs -va and -t options.
3. If "`cmake -DZOOMFIX=ON .`" is run before compiling,
the mirrored window is now visible to screen-sharing applications such as

View File

@@ -23,7 +23,7 @@ add_library( airplay
find_package(PkgConfig REQUIRED)
if( UNIX AND NOT APPLE )
find_library( LIBPLIST NAMES plist plist-2.0 )
find_library( LIBPLIST NAMES plist3 plist plist-2.0 )
elseif( APPLE )
pkg_check_modules( PLIST REQUIRED libplist-2.0 )
find_library( LIBPLIST libplist-2.0.a REQUIRED )

View File

@@ -32,7 +32,7 @@ extern "C" {
typedef struct audio_renderer_s audio_renderer_t;
audio_renderer_t *audio_renderer_init(logger_t *logger, video_renderer_t *video_renderer);
audio_renderer_t *audio_renderer_init(logger_t *logger, video_renderer_t *video_renderer, const char* audiosink);
void audio_renderer_start(audio_renderer_t *renderer);
void audio_renderer_render_buffer(audio_renderer_t *renderer, raop_ntp_t *ntp, unsigned char* data, int data_len, uint64_t pts);
void audio_renderer_set_volume(audio_renderer_t *renderer, float volume);

View File

@@ -51,7 +51,7 @@ static gboolean check_plugins (void)
return ret;
}
audio_renderer_t *audio_renderer_init(logger_t *logger, video_renderer_t *video_renderer) {
audio_renderer_t *audio_renderer_init(logger_t *logger, video_renderer_t *video_renderer, const char* audiosink) {
audio_renderer_t *renderer;
GError *error = NULL;
@@ -63,8 +63,11 @@ audio_renderer_t *audio_renderer_init(logger_t *logger, video_renderer_t *video_
assert(check_plugins ());
renderer->pipeline = gst_parse_launch("appsrc name=audio_source stream-type=0 format=GST_FORMAT_TIME is-live=true ! queue ! decodebin !"
"audioconvert ! volume name=volume ! level ! autoaudiosink sync=false", &error);
GString *launch = g_string_new("appsrc name=audio_source stream-type=0 format=GST_FORMAT_TIME is-live=true ! queue ! decodebin !"
"audioconvert ! volume name=volume ! level ! ");
g_string_append(launch, audiosink);
g_string_append(launch, " sync=false");
renderer->pipeline = gst_parse_launch(launch->str, &error);
g_assert (renderer->pipeline);
renderer->appsrc = gst_bin_get_by_name (GST_BIN (renderer->pipeline), "audio_source");

View File

@@ -35,7 +35,7 @@
#include "renderers/video_renderer.h"
#include "renderers/audio_renderer.h"
#define VERSION "1.37"
#define VERSION "1.38"
#define DEFAULT_NAME "UxPlay"
#define DEFAULT_DEBUG_LOG false
@@ -44,7 +44,7 @@
static int start_server (std::vector<char> hw_addr, std::string name, unsigned short display[5],
unsigned short tcp[3], unsigned short udp[3], videoflip_t videoflip[2],
bool use_audio, bool debug_log, std::string videosink);
bool use_audio, bool debug_log, std::string videosink, std::string audiosink);
static int stop_server ();
@@ -159,13 +159,15 @@ static void print_info (char *name) {
printf(" use \"-p n1,n2,n3\" to set each port, \"n1,n2\" for n3 = n2+1\n");
printf(" \"-p tcp n\" or \"-p udp n\" sets TCP or UDP ports only\n");
printf("-m Use random MAC address (use for concurrent UxPlay's)\n");
printf("-a Turn audio off. video output only\n");
printf("-t n Relaunch server if no connection existed in last n seconds\n");
printf("-vs Choose the GStreamer videosink; default \"autovideosink\"\n");
printf(" choices: ximagesink,xvimagesink,vaapisink,fpsdisplaysink, etc.\n");
printf("-vs Choose the GStreamer videosink; default \"autovideosink\"\n");
printf(" choices: ximagesink,xvimagesink,vaapisink,glimagesink, etc.\n");
printf("-vs 0 Streamed audio only, with no video display window\n");
printf("-as Choose the GStreamer audiosink; default \"autoaudiosink\"\n");
printf(" choices: pulsesink,alsasink,osssink,oss4sink,osxaudiosink,etc.\n");
printf("-as 0 (or -a) Turn audio off, video output only\n");
printf("-d Enable debug logging\n");
printf("-v/-h Displays this help and version information\n");
printf("-v or -h Displays this help and version information\n");
}
bool option_has_value(const int i, const int argc, std::string option, const char *next_arg) {
@@ -296,7 +298,8 @@ int main (int argc, char *argv[]) {
unsigned short display[5] = {0}, tcp[3] = {0}, udp[3] = {0};
videoflip_t videoflip[2] = { NONE , NONE };
std::string videosink = "autovideosink";
std::string audiosink = "autoaudiosink";
#ifdef SUPPRESS_AVAHI_COMPAT_WARNING
// suppress avahi_compat nag message. avahi emits a "nag" warning (once)
// if getenv("AVAHI_COMPAT_NOWARN") returns null.
@@ -373,6 +376,10 @@ int main (int argc, char *argv[]) {
if (!option_has_value(i, argc, arg, argv[i+1])) exit(1);
videosink.erase();
videosink.append(argv[++i]);
} else if (arg == "-as") {
if (!option_has_value(i, argc, arg, argv[i+1])) exit(1);
audiosink.erase();
audiosink.append(argv[++i]);
} else if (arg == "-t") {
if (!option_has_value(i, argc, argv[i], argv[i+1])) exit(1);
server_timeout = 0;
@@ -401,7 +408,7 @@ int main (int argc, char *argv[]) {
relaunch:
connections_stopped = false;
if (start_server(server_hw_addr, server_name, display, tcp, udp,
videoflip,use_audio, debug_log, videosink)) {
videoflip,use_audio, debug_log, videosink, audiosink)) {
return 1;
}
@@ -483,7 +490,7 @@ extern "C" void log_callback (void *cls, int level, const char *msg) {
int start_server (std::vector<char> hw_addr, std::string name, unsigned short display[5],
unsigned short tcp[3], unsigned short udp[3], videoflip_t videoflip[2],
bool use_audio, bool debug_log, std::string videosink) {
bool use_audio, bool debug_log, std::string videosink, std::string audiosink) {
raop_callbacks_t raop_cbs;
memset(&raop_cbs, 0, sizeof(raop_cbs));
raop_cbs.conn_init = conn_init;
@@ -507,6 +514,10 @@ int start_server (std::vector<char> hw_addr, std::string name, unsigned short di
use_video = false;
display[3] = 1; /* set fps to 1 frame per sec when no video will be shown */
}
if(audiosink == "0") {
use_audio = false;
}
raop_set_display(raop, display[0], display[1], display[2], display[3], display[4]);
/* network port selection (ports listed as "0" will be dynamically assigned) */
@@ -533,7 +544,7 @@ int start_server (std::vector<char> hw_addr, std::string name, unsigned short di
if (! use_audio) {
LOGI("Audio disabled");
} else if ((audio_renderer = audio_renderer_init(render_logger, video_renderer)) ==
} else if ((audio_renderer = audio_renderer_init(render_logger, video_renderer, audiosink.c_str())) ==
NULL) {
LOGE("Could not init audio renderer");
stop_server();