From 5f564556c9500bfbf9f49f24c9c948853f4eda7b Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Wed, 8 Feb 2023 01:31:44 -0500 Subject: [PATCH] add a -sync option to activate server-client sync in audio-only mode --- README.html | 18 ++++++++++++++++-- README.md | 14 +++++++++++++- README.txt | 19 +++++++++++++++++-- renderers/audio_renderer.h | 2 +- renderers/audio_renderer_gstreamer.c | 8 ++++++-- uxplay.1 | 3 ++- uxplay.cpp | 7 +++++-- 7 files changed, 60 insertions(+), 11 deletions(-) diff --git a/README.html b/README.html index ca77351..d007c0a 100644 --- a/README.html +++ b/README.html @@ -394,6 +394,15 @@ client drops the connection; since UxPlay-1.58, the option -nohold modifies this behavior so that when a new client requests a connection, it removes the current client and takes over.

+
  • In Audio-Only mode, use the -sync option to +synchronize audio on the server with video on the client. This +introduces a delay that the client adds to account for latency. There is +an option -al x that sets the audio latency x that +the server reports to the client that in principle might modify the +delay a little (this is not clear). Here (non-negative decimal) +x is given in seconds, default is 0.25. Without the +-sync option, there is no audio delay, but the client’s +video lags behind the server’s audio.

  • Since UxPlay-1.54, you can display the accompanying “Cover Art” from sources like Apple Music in Audio-Only (ALAC) mode: run “uxplay -ca <name> &” in the background, then run @@ -680,6 +689,12 @@ the mirror display (X11) window.

    -nh Do not append “@_hostname_” at the end of the AirPlay server name.

    +

    -sync (In Audio-Only (ALAC)) mode: this option +synchronizes audio on the server with video on the client, but causes +the client to add a delay to account for latency, so pausing the stream +will not take effect immediately. This can be mitigated by using the +-al audio latency setting to change the latency (default +0.25 secs) that the server reports to the cient.

    -s wxh (e.g. -s 1920x1080 , which is the default ) sets the display resolution (width and height, in pixels). (This may be a request made to the AirPlay client, and perhaps will not be the final @@ -780,8 +795,7 @@ in (decimal) seconds in Audio-only (ALAC), that is reported to the client. Values in the range [0.0, 10.0] seconds are allowed, and will be converted to a whole number of microseconds. Default is 0.25 sec (250000 usec). (This replaces the -ao option introduced in v1.62, -as a workaround for a problem that is now fixed: it is not clear if -changing the value of x produces any effects, however.)

    +as a workaround for a problem that is now fixed).

    -ca filename provides a file (where filename can include a full path) used for output of “cover art” (from Apple Music, etc.,) in audio-only ALAC mode. This diff --git a/README.md b/README.md index ff0b3a8..d4c388d 100644 --- a/README.md +++ b/README.md @@ -333,6 +333,12 @@ per second. (You can see what framerate is actually streaming by using -vs fpsdi its current client until that client drops the connection; since UxPlay-1.58, the option `-nohold` modifies this behavior so that when a new client requests a connection, it removes the current client and takes over. +* In Audio-Only mode, use the `-sync` option to synchronize audio on the server with video +on the client. This introduces a delay that the client adds to account for latency. There is an +option `-al x` that sets the audio latency _x_ that the server reports to the client that in principle +might modify the delay a little (this is not clear). Here (non-negative decimal) _x_ is given in seconds, default +is 0.25. _Without the `-sync` option, there is no audio delay, but the client's video lags behind the server's audio._ + * Since UxPlay-1.54, you can display the accompanying "Cover Art" from sources like Apple Music in Audio-Only (ALAC) mode: run "`uxplay -ca &`" in the background, then run a image viewer with an autoreload feature: an example is "feh": run "``feh -R 1 ``" @@ -566,6 +572,12 @@ Options: **-nh** Do not append "@_hostname_" at the end of the AirPlay server name. +**-sync** (In Audio-Only (ALAC)) mode: this option synchronizes audio on the server with video on the client, + but causes the client to add a delay to account for latency, so pausing the stream will not take effect + immediately. This can be mitigated by using the `-al` audio latency setting to change the latency (default 0.25 secs) + that the server reports to the cient. + + **-s wxh** (e.g. -s 1920x1080 , which is the default ) sets the display resolution (width and height, in pixels). (This may be a request made to the AirPlay client, and perhaps will not @@ -660,7 +672,7 @@ which will not work if a firewall is running. **-al _x_** specifies an audio latency _x_ in (decimal) seconds in Audio-only (ALAC), that is reported to the client. Values in the range [0.0, 10.0] seconds are allowed, and will be converted to a whole number of microseconds. Default is 0.25 sec (250000 usec). (This replaces the `-ao` option introduced in v1.62, as a workaround for a problem that - is now fixed: it is not clear if changing the value of _x_ produces any effects, however.) + is now fixed). **-ca _filename_** provides a file (where _filename_ can include a full path) used for output of "cover art" (from Apple Music, _etc._,) in audio-only ALAC mode. This file is overwritten with the latest cover art as diff --git a/README.txt b/README.txt index 6bf3857..9399e60 100644 --- a/README.txt +++ b/README.txt @@ -397,6 +397,15 @@ for help with this or other problems. modifies this behavior so that when a new client requests a connection, it removes the current client and takes over. +- In Audio-Only mode, use the `-sync` option to synchronize audio on + the server with video on the client. This introduces a delay that + the client adds to account for latency. There is an option `-al x` + that sets the audio latency *x* that the server reports to the + client that in principle might modify the delay a little (this is + not clear). Here (non-negative decimal) *x* is given in seconds, + default is 0.25. *Without the `-sync` option, there is no audio + delay, but the client's video lags behind the server's audio.* + - Since UxPlay-1.54, you can display the accompanying "Cover Art" from sources like Apple Music in Audio-Only (ALAC) mode: run "`uxplay -ca &`" in the background, then run a image viewer @@ -691,6 +700,13 @@ will also now be the name shown above the mirror display (X11) window. **-nh** Do not append "@_hostname_" at the end of the AirPlay server name. +**-sync** (In Audio-Only (ALAC)) mode: this option synchronizes audio on +the server with video on the client, but causes the client to add a +delay to account for latency, so pausing the stream will not take effect +immediately. This can be mitigated by using the `-al` audio latency +setting to change the latency (default 0.25 secs) that the server +reports to the cient. + **-s wxh** (e.g. -s 1920x1080 , which is the default ) sets the display resolution (width and height, in pixels). (This may be a request made to the AirPlay client, and perhaps will not be the final resolution you @@ -801,8 +817,7 @@ Audio-only (ALAC), that is reported to the client. Values in the range \[0.0, 10.0\] seconds are allowed, and will be converted to a whole number of microseconds. Default is 0.25 sec (250000 usec). (This replaces the `-ao` option introduced in v1.62, as a workaround for a -problem that is now fixed: it is not clear if changing the value of *x* -produces any effects, however.) +problem that is now fixed). **-ca *filename*** provides a file (where *filename* can include a full path) used for output of "cover art" (from Apple Music, *etc.*,) in diff --git a/renderers/audio_renderer.h b/renderers/audio_renderer.h index adeea75..6481eb1 100644 --- a/renderers/audio_renderer.h +++ b/renderers/audio_renderer.h @@ -30,7 +30,7 @@ extern "C" { #include "../lib/logger.h" bool gstreamer_init(); -void audio_renderer_init(logger_t *logger, const char* audiosink); +void audio_renderer_init(logger_t *logger, const char* audiosink, const bool *audio_sync); void audio_renderer_start(unsigned char* compression_type); void audio_renderer_stop(); void audio_renderer_render_buffer(unsigned char* data, int *data_len, unsigned short *seqnum, uint64_t *ntp_time); diff --git a/renderers/audio_renderer_gstreamer.c b/renderers/audio_renderer_gstreamer.c index 239bc16..d1760dd 100644 --- a/renderers/audio_renderer_gstreamer.c +++ b/renderers/audio_renderer_gstreamer.c @@ -82,7 +82,7 @@ static GstClockTime gst_audio_pipeline_base_time = GST_CLOCK_TIME_NONE; static logger_t *logger = NULL; const char * format[NFORMATS]; -void audio_renderer_init(logger_t *render_logger, const char* audiosink) { +void audio_renderer_init(logger_t *render_logger, const char* audiosink, const bool* audio_sync) { GError *error = NULL; GstCaps *caps = NULL; GstClock *clock = gst_system_clock_obtain(); @@ -114,7 +114,11 @@ void audio_renderer_init(logger_t *render_logger, const char* audiosink) { g_string_append (launch, audiosink); switch(i) { case 1: /*ALAC*/ - g_string_append (launch, " sync=true"); + if (*audio_sync) { + g_string_append (launch, " sync=true"); + } else { + g_string_append (launch, " sync=false"); + } break; default: g_string_append (launch, " sync=false"); diff --git a/uxplay.1 b/uxplay.1 index f91280f..60a8125 100644 --- a/uxplay.1 +++ b/uxplay.1 @@ -13,7 +13,8 @@ UxPlay 1.63: An open\-source AirPlay mirroring (+ audio streaming) server. .TP \fB\-nh\fR Do \fBNOT\fR append "@\fIhostname\fR" at end of the AirPlay server name .TP -.B +\fB\-sync\fR (In Audio-Only mode) sync audio on server with video on client. +.TP \fB\-s\fR wxh[@r]Set display resolution [refresh_rate] default 1920x1080[@60] .TP \fB\-o\fR Set display "overscanned" mode on (not usually needed) diff --git a/uxplay.cpp b/uxplay.cpp index e97a4fd..a63eb9f 100644 --- a/uxplay.cpp +++ b/uxplay.cpp @@ -65,7 +65,7 @@ static std::string server_name = DEFAULT_NAME; static dnssd_t *dnssd = NULL; static raop_t *raop = NULL; static logger_t *render_logger = NULL; - +static bool audio_sync = false; static bool relaunch_video = false; static bool reset_loop = false; static unsigned int open_connections= 0; @@ -359,6 +359,7 @@ static void print_info (char *name) { printf("Options:\n"); printf("-n name Specify the network name of the AirPlay server\n"); printf("-nh Do not add \"@hostname\" at the end of the AirPlay server name\n"); + printf("-sync (In Audio-Only mode) sync audio on server with video on client\n"); printf("-s wxh[@r]Set display resolution [refresh_rate] default 1920x1080[@60]\n"); printf("-o Set display \"overscanned\" mode on (not usually needed)\n"); printf("-fs Full-screen (only works with X11, Wayland and VAAPI)\n"); @@ -552,6 +553,8 @@ static void parse_arguments (int argc, char *argv[]) { server_name = std::string(argv[++i]); } else if (arg == "-nh") { do_append_hostname = false; + } else if (arg == "-sync") { + audio_sync = true; } else if (arg == "-s") { if (!option_has_value(i, argc, argv[i], argv[i+1])) exit(1); std::string value(argv[++i]); @@ -1280,7 +1283,7 @@ int main (int argc, char *argv[]) { logger_set_level(render_logger, debug_log ? LOGGER_DEBUG : LOGGER_INFO); if (use_audio) { - audio_renderer_init(render_logger, audiosink.c_str()); + audio_renderer_init(render_logger, audiosink.c_str(), &audio_sync); } else { LOGI("audio_disabled"); }