diff --git a/README.html b/README.html index e33cd2b..3ea87ef 100644 --- a/README.html +++ b/README.html @@ -1,6 +1,7 @@

UxPlay -1.53: AirPlay/AirPlay-Mirror server for Linux, macOS, and Unix.

+id="uxplay-1.54-airplay-mirror-and-airplay-audio-server-for-linux-macos-and-unix.">UxPlay +1.54: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and +Unix.

Now developed at the GitHub site https://github.com/FDH2/UxPlay

Highlights:

This project is a GPLv3 open source unix AirPlay2 Mirror server for Linux, macOS, and *BSD. It was initially developed by antimof using code from RPiPlay, which in turn derives -from antimof using code from +OpenMAX-based RPiPlay, +which in turn derives from AirplayServer, shairplay, and playfair. (The @@ -57,9 +59,10 @@ FreeBSD 13.1. On Raspberry Pi, it is tested on Raspberry Pi OS audio) of iOS/iPadOS/macOS clients (iPhones, iPads, MacBooks) in a window on the server display (with the possibility of sharing that window on screen-sharing applications such as Zoom) on a host running -Linux, macOS, or other unix. UxPlay supports Apple’s AirPlay 2 protocol +Linux, macOS, or other unix. UxPlay supports Apple’s AirPlay2 protocol using “Legacy Pairing”, but some features are missing. (Details of what is publically known about Apple’s AirPlay 2 protocol can be found here, here and here).

The UxPlay server and its client must be on the same local area @@ -72,21 +75,35 @@ the avahi-daemon service, and is included in most Linux distributions (this service can also be provided by macOS, iOS or Windows servers).

Connections to the UxPlay server by iOS/MacOS clients can be -initiated both in AirPlay Mirror mode (which streams lossily-compressed -AAC audio while mirroring the client screen, or in the alternative -AirPlay Audio mode which streams Apple Lossless (ALAC) audio without -screen mirroring (the accompanying cover art in this mode is not -displayed, but metadata is displayed in the terminal). Switching -between these two modes during an active connection is possible: in -Mirror mode, close the mirror window and start an Audio mode connection, -switch back by initiating a Mirror mode connection.

+initiated both in AirPlay Mirror mode (which streams +lossily-compressed AAC audio while mirroring the client screen, or in +the alternative AirPlay Audio mode which streams Apple +Lossless (ALAC) audio without screen mirroring. In +Audio mode, metadata is displayed in the uxplay +terminal; if UxPlay option -ca <name> is used, the +accompanying cover art is also output to a periodically-updated file +<name>, and can be viewed with a (reloading) graphics +viewer of your choice such as feh: run +“uxplay -ca <name> &” in the background, then run +“feh -R 1 <name>” in the foreground; terminate with +“ctrl-C fg ctrl-C”. Switching between +Mirror and Audio modes +during an active connection is possible: in Mirror +mode, stop mirroring (or close the mirror window) and start an +Audio mode connection, switch back by initiating +a Mirror mode connection; cover-art display +stops/restarts as you leave/re-enter Audio +mode.

Possibility @@ -203,7 +220,7 @@ earlier.
  • make
  • sudo make install (you can afterwards uninstall with sudo make uninstall in the same directory in which this was -run)
  • +run).
  • Install GStreamer plugins that you need: sudo apt-get install gstreamer1.0-<plugin>; values of <plugin> needed are: “plugins-base”, @@ -242,11 +259,13 @@ prevents UxPlay from receiving client connection requests unless some network ports are opened. See Troubleshooting below for help with this or other problems.

    -

    One common problem involves GStreamer attempting to use +

    One common problem involves GStreamer attempting to use incorrectly-configured or absent accelerated hardware h264 video decoding (e.g., VAAPI). Try “uxplay -avdec” to force software video decoding; if this works you can then try to fix -accelerated hardware video decoding if you need it. See uxplay -vs waylandsink”. See Usage for more run-time options.

    Raspberry Pi: GStreamer-1.18.4 or later required for hardware video decoding; for 1.20 or earlier, also see

  • libplist-devel avahi-compat-mDNSResponder-devel (+ libX11-devel for ZOOMFIX). The required GStreamer packages are: gstreamer-devel gstreamer-plugins-base-devel gstreamer-plugins-libav -gstreamer-plugins-bad (+ gstreamer-plugins-vaapi for Intel graphics); -you may need to use the version of gstreamer-plugins-libav for OpenSUSE -from Packman “Essentials”.

  • Arch Linux (sudo pacman -Syu) openssl libplist @@ -393,15 +411,6 @@ locks the screen orientation against switching between portrait and landscape mode as the device is rotated).

    Usage

    Options:

    -

    -p allows you to select the network ports used by -UxPlay (these need to be opened if the server is behind a firewall). By -itself, -p sets “legacy” ports TCP 7100, 7000, 7001, UDP 6000, 6001, -7011. -p n (e.g. -p 35000) sets TCP and UDP ports n, n+1, n+2. -p -n1,n2,n3 (comma-separated values) sets each port separately; -p n1,n2 -sets ports n1,n2,n2+1. -p tcp n or -p udp n sets just the TCP or UDP -ports. Ports must be in the range [1024-65535].

    -

    If the -p option is not used, the ports are chosen dynamically -(randomly), which will not work if a firewall is running.

    -n server_name (Default: UxPlay); server_name@_hostname_ will be the name that appears offering AirPlay services to your iPad, iPhone etc, where hostname is the name @@ -430,39 +439,19 @@ Recommendation: don’t use this option unless there is some special reason to use it.

    -fs uses fullscreen mode, but only works with Wayland or VAAPI plugins.

    -

    -fps n sets a maximum frame rate (in frames per -second) for the AirPlay client to stream video; n must be a whole number -less than 256. (The client may choose to serve video at any frame rate -lower than this; default is 30 fps.) A setting below 30 fps might be -useful to reduce latency if you are running more than one instance of -uxplay at the same time. This setting is only an advisory to the -client device, so setting a high value will not force a high -framerate. (You can test using “-vs fpsdisplaysink” to see what -framerate is being received, or use the option -FPSdata which displays -video-stream performance data continuously sent by the client during -video-streaming.)

    -

    -FPSdata Turns on monitoring of regular reports -about video streaming performance that are sent by the client. These -will be displayed in the terminal window if this option is used. The -data is updated by the client at 1 second intervals.

    -

    -m generates a random MAC address to use instead of -the true hardware MAC number of the computer’s network card. (Different -server_name, MAC addresses, and network ports are needed for each -running uxplay if you attempt to run two instances of uxplay on the same -computer.) If UxPlay fails to find the true MAC address of a network -card, (more specifically, the MAC address used by the first active -network interface detected) a random MAC address will be used even if -option -m was not specifed. (Note that a random MAC -address will be different each time UxPlay is started).

    -

    Also: image transforms that had been added to RPiPlay have been -ported to UxPlay:

    -

    -f {H|V|I} implements “videoflip” image transforms: -H = horizontal flip (right-left flip, or mirror image); V = vertical -flip ; I = 180 degree rotation or inversion (which is the combination of -H with V).

    -

    -r {R|L} 90 degree Right (clockwise) or Left -(counter-clockwise) rotations; these are carried out after any --f transforms.

    +

    -p allows you to select the network ports used by +UxPlay (these need to be opened if the server is behind a firewall). By +itself, -p sets “legacy” ports TCP 7100, 7000, 7001, UDP 6000, 6001, +7011. -p n (e.g. -p 35000) sets TCP and UDP ports n, n+1, n+2. -p +n1,n2,n3 (comma-separated values) sets each port separately; -p n1,n2 +sets ports n1,n2,n2+1. -p tcp n or -p udp n sets just the TCP or UDP +ports. Ports must be in the range [1024-65535].

    +

    If the -p option is not used, the ports are chosen dynamically +(randomly), which will not work if a firewall is running.

    +

    -avdec forces use of software h264 decoding using +Gstreamer element avdec_h264 (libav h264 decoder). This option should +prevent autovideosink choosing a hardware-accelerated videosink plugin +such as vaapisink.

    -vp parser choses the GStreamer pipeline’s h264 parser element, default is h264parse. Using quotes “…” allows options to be added.

    @@ -507,10 +496,6 @@ Lite).

    -rpiwl Equivalent to “-v4l2 -vs waylandsink”, for Raspberry Pi “Desktop” systems using the Wayland video compositor (use for Ubuntu 21.10 for Raspberry Pi 4B).

    -

    -avdec forces use of software h264 decoding using -Gstreamer element avdec_h264 (libav h264 decoder). This option should -prevent autovideosink choosing a hardware-accelerated videosink plugin -such as vaapisink.

    -as audiosink chooses the GStreamer audiosink, instead of letting autoaudiosink pick it for you. Some audiosink choices are: pulsesink, alsasink, osssink, oss4sink, and @@ -519,7 +504,21 @@ to be included with the audiosink name. (Some choices of audiosink might not work on your system.)

    -as 0 (or just -a) suppresses playing of streamed audio, but displays streamed video.

    -

    -reset n sets a limit of n consective timeout +

    -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 it arrives. Cover art +(jpeg format) is discarded if this option is not used. Use with a image +viewer that reloads the image if it changes, or regularly (e.g. +once per second.). To achieve this, run +“uxplay -ca [path/to/]filename &” in the background, +then run the the image viewer in the foreground. Example, using +feh as the viewer: run +“feh -R 1 [path/to/]filename” (in the same terminal window +in which uxplay was put into the background). To quit, use +ctrl-C fg ctrl-C to terminate the image viewer, bring +uxplay into the foreground, and terminate it too.

    +

    -reset n sets a limit of n consecutive timeout failures of the client to respond to ntp requests from the server (these are sent every 3 seconds to check if the client is still present). After n failures, the client will be presumed to be offline, and the @@ -531,6 +530,37 @@ client sends the “Stop Mirroring” signal. This option is currently used by default in macOS, as the window created in macOS by GStreamer does not terminate correctly (it causes a segfault) if it is still open when the GStreamer pipeline is closed.

    +

    -FPSdata Turns on monitoring of regular reports +about video streaming performance that are sent by the client. These +will be displayed in the terminal window if this option is used. The +data is updated by the client at 1 second intervals.

    +

    -fps n sets a maximum frame rate (in frames per +second) for the AirPlay client to stream video; n must be a whole number +less than 256. (The client may choose to serve video at any frame rate +lower than this; default is 30 fps.) A setting below 30 fps might be +useful to reduce latency if you are running more than one instance of +uxplay at the same time. This setting is only an advisory to the +client device, so setting a high value will not force a high +framerate. (You can test using “-vs fpsdisplaysink” to see what +framerate is being received, or use the option -FPSdata which displays +video-stream performance data continuously sent by the client during +video-streaming.)

    +

    -f {H|V|I} implements “videoflip” image transforms: +H = horizontal flip (right-left flip, or mirror image); V = vertical +flip ; I = 180 degree rotation or inversion (which is the combination of +H with V).

    +

    -r {R|L} 90 degree Right (clockwise) or Left +(counter-clockwise) rotations; these image transforms are carried out +after any -f transforms.

    +

    -m generates a random MAC address to use instead of +the true hardware MAC number of the computer’s network card. (Different +server_name, MAC addresses, and network ports are needed for each +running uxplay if you attempt to run two instances of uxplay on the same +computer.) If UxPlay fails to find the true MAC address of a network +card, (more specifically, the MAC address used by the first active +network interface detected) a random MAC address will be used even if +option -m was not specifed. (Note that a random MAC +address will be different each time UxPlay is started).

    -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 @@ -723,20 +753,22 @@ connection is reset, the “frozen” mirror screen of the previous connection is left in place, and will be taken over by a new client connection when it is made.

    6. -Failure to decrypt ALL video and audio streams from old or non-Apple -clients:

    -

    This triggers an unending stream of error messages, and means that -the audio decryption key (also used in video decryption) was not -correctly extracted from data sent by the client. This should not happen -for iOS 9.3 or later clients. However, if a client uses the same older -version of the protocol that is used by the Windows-based AirPlay client -emulator AirMyPC, the protocol can be switched to the older -version by the setting OLD_PROTOCOL_CLIENT_USER_AGENT_LIST -in lib/global.h. UxPlay reports the client’s “User Agent” string when it -connects. If some other client also fails to decrypt all audio and -video, try adding its “User Agent” string in place of “xxx” in the entry -“AirMyPC/2.0;xxx” in global.h and rebuild uxplay.

    +id="protocol-issues-such-as-failure-to-decrypt-all-video-and-audio-streams-from-old-or-non-apple-clients">6. +Protocol issues, such as failure to decrypt ALL video and audio streams +from old or non-Apple clients:
  • +

    A protocol failure may trigger an unending stream of error messages, +and means that the audio decryption key (also used in video decryption) +was not correctly extracted from data sent by the client. This should +not happen for iOS 9.3 or later clients. However, if a client uses the +same older version of the protocol that is used by the Windows-based +AirPlay client emulator AirMyPC, the protocol can be switched +to the older version by the setting +OLD_PROTOCOL_CLIENT_USER_AGENT_LIST in +UxPlay/lib/global.h. UxPlay reports the client’s “User +Agent” string when it connects. If some other client also fails to +decrypt all audio and video, try adding its “User Agent” string in place +of “xxx” in the entry “AirMyPC/2.0;xxx” in global.h and rebuild +uxplay.

    Note that Uxplay declares itself to be an AppleTV3,2 with a sourceVersion 220.68; this can also be changed in global.h. It had been thought that it was necessary for UxPlay to claim to be an older 32 bit @@ -748,10 +780,15 @@ AppleTV6,2 with sourceVersion 380.20.1 (an AppleTV 4K 1st gen, introduced 2017, running tvOS 12.2.1); it seems that the use of “legacy” protocol just requires bit 27 (listed as “SupportsLegacyPairing”) of the “features” plist code (reported to the client by the AirPlay server) to -be set.

    +be set. The “features” code and other settings are set in +UxPlay/lib/dnssdint.h.

    ChangeLog

    +

    1.54 2022-06-25 Add support for “Cover Art” display in Audio-only +(ALAC) mode. Reverted a change that caused VAAPI to crash with AMD +POLARIS graphics cards. Minor internal changes to plist code and uxplay +option parsing.

    1.53 2022-06-13 Internal changes to audio sync code, revised -documentation, minor bugfix (fix assertion crash when resent audio +documentation, Minor bugfix (fix assertion crash when resent audio packets are empty).

    1.52 2022-05-05 Cleaned up initial audio sync code, and reformatted streaming debug output (readable aligned timestamps with decimal points diff --git a/README.md b/README.md index 0d17191..e2440c8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# UxPlay 1.53: AirPlay/AirPlay-Mirror server for Linux, macOS, and Unix. +# UxPlay 1.54: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix. ### Now developed at the GitHub site [https://github.com/FDH2/UxPlay](https://github.com/FDH2/UxPlay) (where all user issues should be posted). @@ -6,9 +6,9 @@ Highlights: * GPLv3, open source. - * Support for both AirPlay Mirror and AirPlay Audio-only (Apple Lossless - ALAC) streaming protocols - from current iOS/iPadOS 15.5 clients. + * Originally supported only AirPlay Mirror protocol, now has added support + for AirPlay Audio-only (Apple Lossless ALAC) streaming + from current iOS/iPadOS 15.5 clients. **There is no support for Airplay2 video-streaming protocol, and none is planned.** * macOS computers (2011 or later, both Intel and "Apple Silicon" M1 systems) can act either as AirPlay clients, or as the server running UxPlay. Using AirPlay, UxPlay can @@ -21,8 +21,8 @@ Highlights: "audiosinks", and a fully-user-configurable video streaming pipeline). * Support for server behind a firewall. * **New**: Support for Raspberry Pi, with hardware video acceleration using - Video4Linux2 (which supports both 32- and 64-bit systems, unlike deprecated - OpenMAX (omx), which it replaces). (For GStreamer < 1.22, + Video4Linux2 (vl42), which supports both 32- and 64-bit systems, unlike deprecated + OpenMAX (omx), which is being dropped by RPi distributions in favor of v4l2. (For GStreamer < 1.22, a [patch](https://github.com/FDH2/UxPlay/wiki/Gstreamer-Video4Linux2-plugin-patches) to the GStreamer Video4Linux2 plugin, available in the [UxPlay Wiki](https://github.com/FDH2/UxPlay/wiki), is required, unless @@ -33,7 +33,7 @@ Highlights: This project is a GPLv3 open source unix AirPlay2 Mirror server for Linux, macOS, and \*BSD. It was initially developed by [antimof](http://github.com/antimof/Uxplay) using code -from [RPiPlay](https://github.com/FD-/RPiPlay), which in turn derives from +from OpenMAX-based [RPiPlay](https://github.com/FD-/RPiPlay), which in turn derives from [AirplayServer](https://github.com/KqsMea8/AirplayServer), [shairplay](https://github.com/juhovh/shairplay), and [playfair](https://github.com/EstebanKubata/playfair). (The antimof site is no longer involved in @@ -49,9 +49,10 @@ Its main use is to act like an AppleTV for screen-mirroring (with audio) of iOS/ (iPhones, iPads, MacBooks) in a window on the server display (with the possibility of sharing that window on screen-sharing applications such as Zoom) -on a host running Linux, macOS, or other unix. UxPlay supports Apple's AirPlay 2 +on a host running Linux, macOS, or other unix. UxPlay supports Apple's AirPlay2 protocol using "Legacy Pairing", but some features are missing. (Details of what is publically known about Apple's AirPlay 2 protocol can be found +[here](https://openairplay.github.io/airplay-spec/), [here](https://github.com/SteeBono/airplayreceiver/wiki/AirPlay2-Protocol) and [here](https://emanuelecozzi.net/docs/airplay2)). @@ -64,21 +65,29 @@ through the avahi-daemon service, and is included in most Linux distributions ( service can also be provided by macOS, iOS or Windows servers). Connections to the UxPlay server by -iOS/MacOS clients can be initiated both in AirPlay Mirror mode (which streams +iOS/MacOS clients can be initiated both in **AirPlay Mirror** mode (which streams lossily-compressed AAC audio while mirroring the client screen, -or in the alternative AirPlay Audio mode which streams -Apple Lossless (ALAC) audio without screen mirroring (the accompanying cover art in -this mode is not displayed, but metadata is displayed in the terminal). -_Switching between these two modes during an active connection is -possible: in Mirror mode, close the mirror window and start an Audio mode connection, -switch back by initiating a Mirror mode connection._ +or in the alternative **AirPlay Audio** mode which streams +Apple Lossless (ALAC) audio without screen mirroring. In **Audio** mode, +metadata is displayed in the uxplay terminal; +if UxPlay option ``-ca `` is used, +the accompanying cover art is also output +to a periodically-updated file ``, and can be viewed with +a (reloading) graphics viewer of your choice such as `feh`: +run "`uxplay -ca &`" in the background, then run "``feh -R 1 ``" +in the foreground; terminate with "`ctrl-C fg ctrl-C`". +_Switching between_ **Mirror** _and_ **Audio** _modes during an active connection is +possible: in_ **Mirror** _mode, stop mirroring (or close the mirror window) and start an_ **Audio** _mode connection, +switch back by initiating a_ **Mirror** _mode connection; cover-art display stops/restarts as you leave/re-enter_ **Audio** _mode._ -* **Note that Apple DRM -(as found in Apple TV app content on the client) cannot be decrypted by UxPlay, +* **Note that Apple video-DRM +(as found in AppleTV.app content on the client) cannot be decrypted by UxPlay, and (unlike a true AppleTV), the UxPlay server does not allow the Apple client to run a http connection on the server that directly streams content from the internet to the server, instead of -streaming it to the client, and then re-streaming to the server.** +streaming it to the client, and then re-streaming to the server. Unlike AppleTV.app, DRM-free apps like youtube.app +can be viewed and listened to in Mirror mode, but using the youtube.app icon for AirPlay video will only send +ALAC sound without the accompanying video.** ### Possibility for using hardware-accelerated h264 video-decoding, if available. @@ -186,20 +195,19 @@ for a distribution, use the cmake option `-DNO_MARCH_NATIVE=ON`. such as Zoom, see [ZOOMFIX compile-time option](#zoomfix-compile-time-option) below). **ZOOMFIX is only needed for GStreamer-1.18.x or earlier**. 5. `make` -6. `sudo make install` (you can afterwards uninstall - with `sudo make uninstall` in the same directory in which this was run) -7. Install GStreamer plugins that you - need: `sudo apt-get install gstreamer1.0-`; values of - `` needed are: "**plugins-base**", "**libav**" (for sound), - "**plugins-good**" (for v4l2 hardware h264 decoding) - and "**plugins-bad**" (for h264 decoding). Also needed may - be "**gl**" for OpenGL support (which may be useful, and should - be used with h264 decoding by the NVIDIA GPU), and "**x**" for - X11 support, although these may already be installed; "**vaapi**" - is needed for hardware-accelerated h264 video decoding by Intel - or AMD graphics (but not for use with NVIDIA using proprietary drivers). - Also install "**tools**" to get the utility gst-inspect-1.0 for - examining the GStreamer installation. +6. `sudo make install` (you can afterwards uninstall with ``sudo make uninstall`` + in the same directory in which this was run). +7. Install GStreamer plugins that you need: `sudo apt-get install gstreamer1.0-`; + values of `` needed are: "**plugins-base**", "**libav**" (for sound), + "**plugins-good**" (for v4l2 hardware h264 decoding) + and "**plugins-bad**" (for h264 decoding). Also needed may + be "**gl**" for OpenGL support (which may be useful, and should + be used with h264 decoding by the NVIDIA GPU), and "**x**" for + X11 support, although these may already be installed; "**vaapi**" + is needed for hardware-accelerated h264 video decoding by Intel + or AMD graphics (but not for use with NVIDIA using proprietary drivers). + Also install "**tools**" to get the utility gst-inspect-1.0 for + examining the GStreamer installation. _If you intend to modify the code, use a separate "build" directory: replace_ "`cmake [ ] .`" _by_ "``mkdir build ; cd build ; cmake [ ] ..``"; _you can then clean @@ -224,11 +232,12 @@ UxPlay from receiving client connection requests unless some network ports are opened. See [Troubleshooting](#troubleshooting) below for help with this or other problems. -One common problem involves GStreamer +**One common problem involves GStreamer attempting to use incorrectly-configured or absent accelerated hardware h264 video decoding (e.g., VAAPI). Try "`uxplay -avdec`" to force software video decoding; if this works you can -then try to fix accelerated hardware video decoding if you need it. +then try to fix accelerated hardware video decoding if you need it, or just uninstall the GStreamer VAAPI plugin. If +your system uses the Wayland compositor for graphics, use "`uxplay -vs waylandsink`".** See [Usage](#usage) for more run-time options. **Raspberry Pi**: GStreamer-1.18.4 or later required for hardware video decoding; for 1.20 or earlier, also see @@ -262,8 +271,8 @@ gstreamer1-devel gstreamer1-plugins-base-devel gstreamer1-libav gstreamer1-plugi * **OpenSUSE:** (sudo zypper install) libopenssl-devel libplist-devel avahi-compat-mDNSResponder-devel (+ libX11-devel for ZOOMFIX). The required -GStreamer packages are: gstreamer-devel gstreamer-plugins-base-devel gstreamer-plugins-libav gstreamer-plugins-bad (+ gstreamer-plugins-vaapi for Intel graphics); -you may need to use the version of gstreamer-plugins-libav for OpenSUSE from [Packman](https://ftp.gwdg.de/pub/linux/misc/packman/suse/) "Essentials". +GStreamer packages are: gstreamer-devel gstreamer-plugins-base-devel gstreamer-plugins-libav gstreamer-plugins-bad (+ gstreamer-plugins-vaapi for Intel graphics); in some cases, +you may need to use gstreamer packages for OpenSUSE from [Packman](https://ftp.gwdg.de/pub/linux/misc/packman/suse/) "Essentials". * **Arch Linux** @@ -350,24 +359,12 @@ as the device is rotated). Options: -**-p** allows you to select the network ports used by UxPlay (these need - to be opened if the server is behind a firewall). By itself, -p sets - "legacy" ports TCP 7100, 7000, 7001, UDP 6000, 6001, 7011. -p n (e.g. -p - 35000) sets TCP and UDP ports n, n+1, n+2. -p n1,n2,n3 (comma-separated - values) sets each port separately; -p n1,n2 sets ports n1,n2,n2+1. -p tcp n - or -p udp n sets just the TCP or UDP ports. Ports must be in the range - [1024-65535]. - -If the -p option is not used, the ports are chosen dynamically (randomly), -which will not work if a firewall is running. - **-n server_name** (Default: UxPlay); server_name@_hostname_ will be the name that appears offering AirPlay services to your iPad, iPhone etc, where _hostname_ is the name of the server running uxplay. This 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. - **-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 @@ -391,40 +388,20 @@ which will not work if a firewall is running. **-fs** uses fullscreen mode, but only works with Wayland or VAAPI plugins. -**-fps n** sets a maximum frame rate (in frames per second) for the AirPlay - client to stream video; n must be a whole number less than 256. - (The client may choose to serve video at any frame rate lower - than this; default is 30 fps.) A setting below 30 fps might be useful to - reduce latency if you are running more than one instance of uxplay at the same time. - _This setting is only an advisory to - the client device, so setting a high value will not force a high framerate._ - (You can test using "-vs fpsdisplaysink" to see what framerate is being - received, or use the option -FPSdata which displays video-stream performance data - continuously sent by the client during video-streaming.) +**-p** allows you to select the network ports used by UxPlay (these need + to be opened if the server is behind a firewall). By itself, -p sets + "legacy" ports TCP 7100, 7000, 7001, UDP 6000, 6001, 7011. -p n (e.g. -p + 35000) sets TCP and UDP ports n, n+1, n+2. -p n1,n2,n3 (comma-separated + values) sets each port separately; -p n1,n2 sets ports n1,n2,n2+1. -p tcp n + or -p udp n sets just the TCP or UDP ports. Ports must be in the range + [1024-65535]. -**-FPSdata** Turns on monitoring of regular reports about video streaming performance - that are sent by the client. These will be displayed in the terminal window if this - option is used. The data is updated by the client at 1 second intervals. - -**-m** generates a random MAC address to use instead of the true hardware MAC - number of the computer's network card. (Different server_name, MAC - addresses, and network ports are needed for each running uxplay if you - attempt to run two instances of uxplay on the same computer.) - If UxPlay fails to find the true MAC address of a network card, (more - specifically, the MAC address used by the first active network interface detected) - a random MAC address will be used even if option **-m** was not specifed. - (Note that a random MAC address will be different each time UxPlay is started). - - -Also: image transforms that had been added to RPiPlay have been ported to UxPlay: - -**-f {H|V|I}** implements "videoflip" image transforms: H = horizontal flip -(right-left flip, or mirror image); V = vertical flip ; I = -180 degree rotation or inversion (which is the combination of H with V). - -**-r {R|L}** 90 degree Right (clockwise) or Left (counter-clockwise) - rotations; these are carried out after any **-f** transforms. +If the -p option is not used, the ports are chosen dynamically (randomly), +which will not work if a firewall is running. +**-avdec** forces use of software h264 decoding using Gstreamer element avdec_h264 (libav h264 decoder). This + option should prevent autovideosink choosing a hardware-accelerated videosink plugin such as vaapisink. + **-vp _parser_** choses the GStreamer pipeline's h264 parser element, default is h264parse. Using quotes "..." allows options to be added. @@ -463,9 +440,6 @@ Also: image transforms that had been added to RPiPlay have been ported to UxPlay Pi "Desktop" systems using the Wayland video compositor (use for Ubuntu 21.10 for Raspberry Pi 4B). -**-avdec** forces use of software h264 decoding using Gstreamer element avdec_h264 (libav h264 decoder). This - option should prevent autovideosink choosing a hardware-accelerated videosink plugin such as vaapisink. - **-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 @@ -474,7 +448,15 @@ Also: image transforms that had been added to RPiPlay have been ported to UxPlay **-as 0** (or just **-a**) suppresses playing of streamed audio, but displays streamed video. -**-reset n** sets a limit of n consective timeout failures of the client to respond to ntp requests +**-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 + it arrives. Cover art (jpeg format) is discarded if this option is not used. Use with a image viewer that reloads the image + if it changes, or regularly (_e.g._ once per second.). To achieve this, run "`uxplay -ca [path/to/]filename &`" in the background, + then run the the image viewer in the foreground. Example, using `feh` as the viewer: run "``feh -R 1 [path/to/]filename``" (in + the same terminal window in which uxplay was put into the background). To quit, use ```ctrl-C fg ctrl-C``` to terminate + the image viewer, bring ``uxplay`` into the foreground, and terminate it too. + +**-reset n** sets a limit of n consecutive timeout failures of the client to respond to ntp requests from the server (these are sent every 3 seconds to check if the client is still present). After n failures, the client will be presumed to be offline, and the connection will be reset to allow a new connection. The default value of n is 5; the value n = 0 means "no limit" on timeouts. @@ -484,6 +466,37 @@ Also: image transforms that had been added to RPiPlay have been ported to UxPlay as the window created in macOS by GStreamer does not terminate correctly (it causes a segfault) if it is still open when the GStreamer pipeline is closed._ +**-FPSdata** Turns on monitoring of regular reports about video streaming performance + that are sent by the client. These will be displayed in the terminal window if this + option is used. The data is updated by the client at 1 second intervals. + +**-fps n** sets a maximum frame rate (in frames per second) for the AirPlay + client to stream video; n must be a whole number less than 256. + (The client may choose to serve video at any frame rate lower + than this; default is 30 fps.) A setting below 30 fps might be useful to + reduce latency if you are running more than one instance of uxplay at the same time. + _This setting is only an advisory to + the client device, so setting a high value will not force a high framerate._ + (You can test using "-vs fpsdisplaysink" to see what framerate is being + received, or use the option -FPSdata which displays video-stream performance data + continuously sent by the client during video-streaming.) + +**-f {H|V|I}** implements "videoflip" image transforms: H = horizontal flip + (right-left flip, or mirror image); V = vertical flip ; I = + 180 degree rotation or inversion (which is the combination of H with V). + +**-r {R|L}** 90 degree Right (clockwise) or Left (counter-clockwise) + rotations; these image transforms are carried out after any **-f** transforms. + +**-m** generates a random MAC address to use instead of the true hardware MAC + number of the computer's network card. (Different server_name, MAC + addresses, and network ports are needed for each running uxplay if you + attempt to run two instances of uxplay on the same computer.) + If UxPlay fails to find the true MAC address of a network card, (more + specifically, the MAC address used by the first active network interface detected) + a random MAC address will be used even if option **-m** was not specifed. + (Note that a random MAC address will be different each time UxPlay is started). + **-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 if the Server is not visible to new Clients that were inactive when the Server was launched, and an idle Bonjour @@ -631,15 +644,16 @@ default limit is not right for your network, it can be modified using the opti starts to recover after ntp timeouts, a corrupt video packet from before the timeout may trigger a "connection reset by peer" error, which also causes UxPlay to reset the connection. When the connection is reset, the "frozen" mirror screen of the previous connection is left in place, and will be taken over by a new client connection when it is made. -### 6. Failure to decrypt ALL video and audio streams from old or non-Apple clients: +### 6. Protocol issues, such as failure to decrypt ALL video and audio streams from old or non-Apple clients: -This triggers an unending stream of error messages, and means that the +A protocol failure may trigger an unending stream of error messages, and means that the audio decryption key (also used in video decryption) was not correctly extracted from data sent by the client. This should not happen for iOS 9.3 or later clients. However, if a client uses the same older version of the protocol that is used by the Windows-based AirPlay client emulator _AirMyPC_, the protocol can be switched to the older version -by the setting ```OLD_PROTOCOL_CLIENT_USER_AGENT_LIST``` in lib/global.h. +by the setting ```OLD_PROTOCOL_CLIENT_USER_AGENT_LIST``` +in `UxPlay/lib/global.h`. UxPlay reports the client's "User Agent" string when it connects. If some other client also fails to decrypt all audio and video, try adding its "User Agent" string in place of "xxx" in the entry "AirMyPC/2.0;xxx" @@ -656,10 +670,15 @@ sourceVersion 380.20.1 (an AppleTV 4K 1st gen, introduced 2017, running tvOS 12.2.1); it seems that the use of "legacy" protocol just requires bit 27 (listed as "SupportsLegacyPairing") of the "features" plist code (reported to the client by the AirPlay server) to be set. +The "features" code and other settings are set in `UxPlay/lib/dnssdint.h`. # ChangeLog -1.53 2022-06-13 Internal changes to audio sync code, revised documentation, - minor bugfix (fix assertion crash when resent audio packets are empty). +1.54 2022-06-25 Add support for "Cover Art" display in Audio-only (ALAC) mode. Reverted a change + that caused VAAPI to crash with AMD POLARIS graphics cards. Minor internal changes to + plist code and uxplay option parsing. + +1.53 2022-06-13 Internal changes to audio sync code, revised documentation, + Minor bugfix (fix assertion crash when resent audio packets are empty). 1.52 2022-05-05 Cleaned up initial audio sync code, and reformatted streaming debug output (readable aligned timestamps with diff --git a/README.txt b/README.txt index 112f4d6..b2dd436 100644 --- a/README.txt +++ b/README.txt @@ -1,13 +1,14 @@ -# UxPlay 1.53: AirPlay/AirPlay-Mirror server for Linux, macOS, and Unix. +# UxPlay 1.54: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix. ### Now developed at the GitHub site (where all user issues should be posted). Highlights: - GPLv3, open source. -- Support for both AirPlay Mirror and AirPlay Audio-only (Apple - Lossless ALAC) streaming protocols from current iOS/iPadOS 15.5 - clients. +- Originally supported only AirPlay Mirror protocol, now has added + support for AirPlay Audio-only (Apple Lossless ALAC) streaming from + current iOS/iPadOS 15.5 clients. **There is no support for Airplay2 + video-streaming protocol, and none is planned.** - macOS computers (2011 or later, both Intel and "Apple Silicon" M1 systems) can act either as AirPlay clients, or as the server running UxPlay. Using AirPlay, UxPlay can emulate a second display for macOS @@ -21,9 +22,9 @@ Highlights: pipeline). - Support for server behind a firewall. - **New**: Support for Raspberry Pi, with hardware video acceleration - using Video4Linux2 (which supports both 32- and 64-bit systems, - unlike deprecated OpenMAX (omx), which it replaces). (For GStreamer - \< 1.22, a + using Video4Linux2 (vl42), which supports both 32- and 64-bit + systems, unlike deprecated OpenMAX (omx), which is being dropped by + RPi distributions in favor of v4l2. (For GStreamer \< 1.22, a [patch](https://github.com/FDH2/UxPlay/wiki/Gstreamer-Video4Linux2-plugin-patches) to the GStreamer Video4Linux2 plugin, available in the [UxPlay Wiki](https://github.com/FDH2/UxPlay/wiki), is required, unless your @@ -34,8 +35,8 @@ Highlights: This project is a GPLv3 open source unix AirPlay2 Mirror server for Linux, macOS, and \*BSD. It was initially developed by [antimof](http://github.com/antimof/Uxplay) using code from -[RPiPlay](https://github.com/FD-/RPiPlay), which in turn derives from -[AirplayServer](https://github.com/KqsMea8/AirplayServer), +OpenMAX-based [RPiPlay](https://github.com/FD-/RPiPlay), which in turn +derives from [AirplayServer](https://github.com/KqsMea8/AirplayServer), [shairplay](https://github.com/juhovh/shairplay), and [playfair](https://github.com/EstebanKubata/playfair). (The antimof site is no longer involved in development, but periodically posts updates @@ -52,9 +53,10 @@ Its main use is to act like an AppleTV for screen-mirroring (with audio) of iOS/iPadOS/macOS clients (iPhones, iPads, MacBooks) in a window on the server display (with the possibility of sharing that window on screen-sharing applications such as Zoom) on a host running Linux, -macOS, or other unix. UxPlay supports Apple's AirPlay 2 protocol using +macOS, or other unix. UxPlay supports Apple's AirPlay2 protocol using "Legacy Pairing", but some features are missing. (Details of what is publically known about Apple's AirPlay 2 protocol can be found +[here](https://openairplay.github.io/airplay-spec/), [here](https://github.com/SteeBono/airplayreceiver/wiki/AirPlay2-Protocol) and [here](https://emanuelecozzi.net/docs/airplay2)). @@ -68,21 +70,31 @@ included in most Linux distributions (this service can also be provided by macOS, iOS or Windows servers). Connections to the UxPlay server by iOS/MacOS clients can be initiated -both in AirPlay Mirror mode (which streams lossily-compressed AAC audio -while mirroring the client screen, or in the alternative AirPlay Audio -mode which streams Apple Lossless (ALAC) audio without screen mirroring -(the accompanying cover art in this mode is not displayed, but metadata -is displayed in the terminal). *Switching between these two modes during -an active connection is possible: in Mirror mode, close the mirror -window and start an Audio mode connection, switch back by initiating a -Mirror mode connection.* +both in **AirPlay Mirror** mode (which streams lossily-compressed AAC +audio while mirroring the client screen, or in the alternative **AirPlay +Audio** mode which streams Apple Lossless (ALAC) audio without screen +mirroring. In **Audio** mode, metadata is displayed in the uxplay +terminal; if UxPlay option `-ca ` is used, the accompanying cover +art is also output to a periodically-updated file ``, and can be +viewed with a (reloading) graphics viewer of your choice such as `feh`: +run "`uxplay -ca &`" in the background, then run +"`feh -R 1 `" in the foreground; terminate with +"`ctrl-C fg ctrl-C`". *Switching between* **Mirror** *and* **Audio** +*modes during an active connection is possible: in* **Mirror** *mode, +stop mirroring (or close the mirror window) and start an* **Audio** +*mode connection, switch back by initiating a* **Mirror** *mode +connection; cover-art display stops/restarts as you leave/re-enter* +**Audio** *mode.* -- **Note that Apple DRM (as found in Apple TV app content on the +- **Note that Apple video-DRM (as found in AppleTV.app content on the client) cannot be decrypted by UxPlay, and (unlike a true AppleTV), the UxPlay server does not allow the Apple client to run a http connection on the server that directly streams content from the internet to the server, instead of streaming it to the client, and - then re-streaming to the server.** + then re-streaming to the server. Unlike AppleTV.app, DRM-free apps + like youtube.app can be viewed and listened to in Mirror mode, but + using the youtube.app icon for AirPlay video will only send ALAC + sound without the accompanying video.** ### Possibility for using hardware-accelerated h264 video-decoding, if available. @@ -204,7 +216,7 @@ packaging for a distribution, use the cmake option needed for GStreamer-1.18.x or earlier**. 5. `make` 6. `sudo make install` (you can afterwards uninstall with - `sudo make uninstall` in the same directory in which this was run) + `sudo make uninstall` in the same directory in which this was run). 7. Install GStreamer plugins that you need: `sudo apt-get install gstreamer1.0-`; values of `` needed are: "**plugins-base**", "**libav**" (for sound), @@ -244,11 +256,13 @@ prevents UxPlay from receiving client connection requests unless some network ports are opened. See [Troubleshooting](#troubleshooting) below for help with this or other problems. -One common problem involves GStreamer attempting to use +**One common problem involves GStreamer attempting to use incorrectly-configured or absent accelerated hardware h264 video decoding (e.g., VAAPI). Try "`uxplay -avdec`" to force software video decoding; if this works you can then try to fix accelerated hardware -video decoding if you need it. See [Usage](#usage) for more run-time +video decoding if you need it, or just uninstall the GStreamer VAAPI +plugin. If your system uses the Wayland compositor for graphics, use +"`uxplay -vs waylandsink`".** See [Usage](#usage) for more run-time options. **Raspberry Pi**: GStreamer-1.18.4 or later required for hardware video @@ -292,8 +306,8 @@ Terminal output is saved to FILE (which can be /dev/null to discard it). required GStreamer packages are: gstreamer-devel gstreamer-plugins-base-devel gstreamer-plugins-libav gstreamer-plugins-bad (+ gstreamer-plugins-vaapi for Intel - graphics); you may need to use the version of - gstreamer-plugins-libav for OpenSUSE from + graphics); in some cases, you may need to use gstreamer packages for + OpenSUSE from [Packman](https://ftp.gwdg.de/pub/linux/misc/packman/suse/) "Essentials". @@ -403,17 +417,6 @@ landscape mode as the device is rotated). Options: -**-p** allows you to select the network ports used by UxPlay (these need -to be opened if the server is behind a firewall). By itself, -p sets -"legacy" ports TCP 7100, 7000, 7001, UDP 6000, 6001, 7011. -p n (e.g. -p -35000) sets TCP and UDP ports n, n+1, n+2. -p n1,n2,n3 (comma-separated -values) sets each port separately; -p n1,n2 sets ports n1,n2,n2+1. -p -tcp n or -p udp n sets just the TCP or UDP ports. Ports must be in the -range \[1024-65535\]. - -If the -p option is not used, the ports are chosen dynamically -(randomly), which will not work if a firewall is running. - **-n server_name** (Default: UxPlay); server_name@\_hostname\_ will be the name that appears offering AirPlay services to your iPad, iPhone etc, where *hostname* is the name of the server running uxplay. This @@ -446,41 +449,21 @@ reason to use it. **-fs** uses fullscreen mode, but only works with Wayland or VAAPI plugins. -**-fps n** sets a maximum frame rate (in frames per second) for the -AirPlay client to stream video; n must be a whole number less than 256. -(The client may choose to serve video at any frame rate lower than this; -default is 30 fps.) A setting below 30 fps might be useful to reduce -latency if you are running more than one instance of uxplay at the same -time. *This setting is only an advisory to the client device, so setting -a high value will not force a high framerate.* (You can test using "-vs -fpsdisplaysink" to see what framerate is being received, or use the -option -FPSdata which displays video-stream performance data -continuously sent by the client during video-streaming.) +**-p** allows you to select the network ports used by UxPlay (these need +to be opened if the server is behind a firewall). By itself, -p sets +"legacy" ports TCP 7100, 7000, 7001, UDP 6000, 6001, 7011. -p n (e.g. -p +35000) sets TCP and UDP ports n, n+1, n+2. -p n1,n2,n3 (comma-separated +values) sets each port separately; -p n1,n2 sets ports n1,n2,n2+1. -p +tcp n or -p udp n sets just the TCP or UDP ports. Ports must be in the +range \[1024-65535\]. -**-FPSdata** Turns on monitoring of regular reports about video -streaming performance that are sent by the client. These will be -displayed in the terminal window if this option is used. The data is -updated by the client at 1 second intervals. +If the -p option is not used, the ports are chosen dynamically +(randomly), which will not work if a firewall is running. -**-m** generates a random MAC address to use instead of the true -hardware MAC number of the computer's network card. (Different -server_name, MAC addresses, and network ports are needed for each -running uxplay if you attempt to run two instances of uxplay on the same -computer.) If UxPlay fails to find the true MAC address of a network -card, (more specifically, the MAC address used by the first active -network interface detected) a random MAC address will be used even if -option **-m** was not specifed. (Note that a random MAC address will be -different each time UxPlay is started). - -Also: image transforms that had been added to RPiPlay have been ported -to UxPlay: - -**-f {H\|V\|I}** implements "videoflip" image transforms: H = horizontal -flip (right-left flip, or mirror image); V = vertical flip ; I = 180 -degree rotation or inversion (which is the combination of H with V). - -**-r {R\|L}** 90 degree Right (clockwise) or Left (counter-clockwise) -rotations; these are carried out after any **-f** transforms. +**-avdec** forces use of software h264 decoding using Gstreamer element +avdec_h264 (libav h264 decoder). This option should prevent +autovideosink choosing a hardware-accelerated videosink plugin such as +vaapisink. **-vp *parser*** choses the GStreamer pipeline's h264 parser element, default is h264parse. Using quotes "..." allows options to be added. @@ -530,11 +513,6 @@ systems using the framebuffer, like RPi OS Bullseye Lite). "Desktop" systems using the Wayland video compositor (use for Ubuntu 21.10 for Raspberry Pi 4B). -**-avdec** forces use of software h264 decoding using Gstreamer element -avdec_h264 (libav h264 decoder). This option should prevent -autovideosink choosing a hardware-accelerated videosink plugin such as -vaapisink. - **-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 @@ -544,12 +522,25 @@ name. (Some choices of audiosink might not work on your system.) **-as 0** (or just **-a**) suppresses playing of streamed audio, but displays streamed video. -**-reset n** sets a limit of n consective timeout failures of the client -to respond to ntp requests from the server (these are sent every 3 -seconds to check if the client is still present). After n failures, the -client will be presumed to be offline, and the connection will be reset -to allow a new connection. The default value of n is 5; the value n = 0 -means "no limit" on timeouts. +**-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 it arrives. Cover art (jpeg format) is discarded if this option is +not used. Use with a image viewer that reloads the image if it changes, +or regularly (*e.g.* once per second.). To achieve this, run +"`uxplay -ca [path/to/]filename &`" in the background, then run the the +image viewer in the foreground. Example, using `feh` as the viewer: run +"`feh -R 1 [path/to/]filename`" (in the same terminal window in which +uxplay was put into the background). To quit, use `ctrl-C fg ctrl-C` to +terminate the image viewer, bring `uxplay` into the foreground, and +terminate it too. + +**-reset n** sets a limit of n consecutive timeout failures of the +client to respond to ntp requests from the server (these are sent every +3 seconds to check if the client is still present). After n failures, +the client will be presumed to be offline, and the connection will be +reset to allow a new connection. The default value of n is 5; the value +n = 0 means "no limit" on timeouts. **-nc** maintains previous UxPlay \< 1.45 behavior that does **not close** the video window when the the client sends the "Stop Mirroring" @@ -558,6 +549,40 @@ window created in macOS by GStreamer does not terminate correctly (it causes a segfault) if it is still open when the GStreamer pipeline is closed.* +**-FPSdata** Turns on monitoring of regular reports about video +streaming performance that are sent by the client. These will be +displayed in the terminal window if this option is used. The data is +updated by the client at 1 second intervals. + +**-fps n** sets a maximum frame rate (in frames per second) for the +AirPlay client to stream video; n must be a whole number less than 256. +(The client may choose to serve video at any frame rate lower than this; +default is 30 fps.) A setting below 30 fps might be useful to reduce +latency if you are running more than one instance of uxplay at the same +time. *This setting is only an advisory to the client device, so setting +a high value will not force a high framerate.* (You can test using "-vs +fpsdisplaysink" to see what framerate is being received, or use the +option -FPSdata which displays video-stream performance data +continuously sent by the client during video-streaming.) + +**-f {H\|V\|I}** implements "videoflip" image transforms: H = horizontal +flip (right-left flip, or mirror image); V = vertical flip ; I = 180 +degree rotation or inversion (which is the combination of H with V). + +**-r {R\|L}** 90 degree Right (clockwise) or Left (counter-clockwise) +rotations; these image transforms are carried out after any **-f** +transforms. + +**-m** generates a random MAC address to use instead of the true +hardware MAC number of the computer's network card. (Different +server_name, MAC addresses, and network ports are needed for each +running uxplay if you attempt to run two instances of uxplay on the same +computer.) If UxPlay fails to find the true MAC address of a network +card, (more specifically, the MAC address used by the first active +network interface detected) a random MAC address will be used even if +option **-m** was not specifed. (Note that a random MAC address will be +different each time UxPlay is started). + **-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 if the Server is not visible @@ -764,19 +789,19 @@ causes UxPlay to reset the connection. When the connection is reset, the "frozen" mirror screen of the previous connection is left in place, and will be taken over by a new client connection when it is made. -### 6. Failure to decrypt ALL video and audio streams from old or non-Apple clients: +### 6. Protocol issues, such as failure to decrypt ALL video and audio streams from old or non-Apple clients: -This triggers an unending stream of error messages, and means that the -audio decryption key (also used in video decryption) was not correctly -extracted from data sent by the client. This should not happen for iOS -9.3 or later clients. However, if a client uses the same older version -of the protocol that is used by the Windows-based AirPlay client -emulator *AirMyPC*, the protocol can be switched to the older version by -the setting `OLD_PROTOCOL_CLIENT_USER_AGENT_LIST` in lib/global.h. -UxPlay reports the client's "User Agent" string when it connects. If -some other client also fails to decrypt all audio and video, try adding -its "User Agent" string in place of "xxx" in the entry "AirMyPC/2.0;xxx" -in global.h and rebuild uxplay. +A protocol failure may trigger an unending stream of error messages, and +means that the audio decryption key (also used in video decryption) was +not correctly extracted from data sent by the client. This should not +happen for iOS 9.3 or later clients. However, if a client uses the same +older version of the protocol that is used by the Windows-based AirPlay +client emulator *AirMyPC*, the protocol can be switched to the older +version by the setting `OLD_PROTOCOL_CLIENT_USER_AGENT_LIST` in +`UxPlay/lib/global.h`. UxPlay reports the client's "User Agent" string +when it connects. If some other client also fails to decrypt all audio +and video, try adding its "User Agent" string in place of "xxx" in the +entry "AirMyPC/2.0;xxx" in global.h and rebuild uxplay. Note that Uxplay declares itself to be an AppleTV3,2 with a sourceVersion 220.68; this can also be changed in global.h. It had been @@ -788,12 +813,18 @@ UxPlay still works if it declares itself as an AppleTV6,2 with sourceVersion 380.20.1 (an AppleTV 4K 1st gen, introduced 2017, running tvOS 12.2.1); it seems that the use of "legacy" protocol just requires bit 27 (listed as "SupportsLegacyPairing") of the "features" plist code -(reported to the client by the AirPlay server) to be set. +(reported to the client by the AirPlay server) to be set. The "features" +code and other settings are set in `UxPlay/lib/dnssdint.h`. # ChangeLog +1.54 2022-06-25 Add support for "Cover Art" display in Audio-only (ALAC) +mode. Reverted a change that caused VAAPI to crash with AMD POLARIS +graphics cards. Minor internal changes to plist code and uxplay option +parsing. + 1.53 2022-06-13 Internal changes to audio sync code, revised -documentation, minor bugfix (fix assertion crash when resent audio +documentation, Minor bugfix (fix assertion crash when resent audio packets are empty). 1.52 2022-05-05 Cleaned up initial audio sync code, and reformatted diff --git a/uxplay.1 b/uxplay.1 index 0a0fa4c..fbe8080 100644 --- a/uxplay.1 +++ b/uxplay.1 @@ -1,4 +1,4 @@ -.TH UXPLAY "1" "June 2022" "1.53" "User Commands" +.TH UXPLAY "1" "June 2022" "1.54" "User Commands" .SH NAME uxplay \- start AirPlay server .SH SYNOPSIS @@ -16,16 +16,10 @@ UxPlay 1.53: An open\-source AirPlay mirroring server based on RPiPlay .B \fB\-s\fR wxh[@r]Set display resolution [refresh_rate] default 1920x1080[@60] .TP -\fB\-o\fR Set mirror "overscanned" mode on (not usually needed) +\fB\-o\fR Set display "overscanned" mode on (not usually needed) .TP \fB-fs\fR Full-screen (only with Wayland and VAAPI plugins) .TP -\fB\-fps\fR n Set maximum allowed streaming framerate, default 30 -.TP -\fB\-f\fR {H|V|I}Horizontal|Vertical flip, or both=Inversion=rotate 180 deg -.TP -\fB\-r\fR {R|L} Rotate 90 degrees Right (cw) or Left (ccw) -.TP \fB\-p\fR Use legacy ports UDP 6000:6001:7011 TCP 7000:7001:7100 .TP \fB\-p\fR n Use TCP and UDP ports n,n+1,n+2. range 1024\-65535 @@ -35,9 +29,12 @@ UxPlay 1.53: An open\-source AirPlay mirroring server based on RPiPlay "\-p tcp n" or "\-p udp n" sets TCP or UDP ports separately. .PP .TP -\fB\-m\fR Use random MAC address (use for concurrent UxPlay's) -.TP -\fB\-t\fR n Relaunch server if no connection existed in last n seconds +\fB\-avdec\fR Force software h264 video decoding with libav decoder. + + + + + .TP \fB\-vp\fI prs \fR Choose GStreamer h264 parser; default "h264parse" .TP @@ -68,8 +65,6 @@ UxPlay 1.53: An open\-source AirPlay mirroring server based on RPiPlay .TP \fB\-rpiwl\fR Same as "-v4l2 -vs waylandsink" for RPi using Wayland. .TP -\fB\-avdec\fR Force software h264 video decoding with libav decoder. -.TP \fB\-as\fI sink\fR Choose the GStreamer audiosink; default "autoaudiosink" .IP choices:pulsesink,alsasink,osssink,oss4sink,osxaudiosink,.. @@ -77,12 +72,24 @@ UxPlay 1.53: An open\-source AirPlay mirroring server based on RPiPlay .TP \fB\-as\fR 0 (or \fB\-a\fR) Turn audio off, streamed video only. .TP -\fB\-reset\fR n Reset after 3n seconds client silence (default 10, 0=never). +\fB\-ca\fI fn \fR In Airplay Audio (ALAC) mode, write cover-art to file fn. +.TP +\fB\-reset\fR n Reset after 3n seconds client silence (default 5, 0=never). .TP \fB\-nc\fR Do not close video window when client stops mirroring .TP \fB\-FPSdata\fR Show video-streaming performance reports sent by client. .TP +\fB\-fps\fR n Set maximum allowed streaming framerate, default 30 +.TP +\fB\-f\fR {H|V|I}Horizontal|Vertical flip, or both=Inversion=rotate 180 deg +.TP +\fB\-r\fR {R|L} Rotate 90 degrees Right (cw) or Left (ccw) +.TP +\fB\-m\fR Use random MAC address (use for concurrent UxPlay's) +.TP +\fB\-t\fR n Relaunch server if no connection existed in last n seconds +.TP \fB\-vdmp\fR [n] Dump h264 video output to "fn.h264"; fn="videodump", change .IP with "-vdmp [n] filename". If [n] is given, file fn.x.h264 diff --git a/uxplay.cpp b/uxplay.cpp index 372e86d..5e26e09 100644 --- a/uxplay.cpp +++ b/uxplay.cpp @@ -44,7 +44,7 @@ #include "renderers/video_renderer.h" #include "renderers/audio_renderer.h" -#define VERSION "1.53" +#define VERSION "1.54" #define DEFAULT_NAME "UxPlay" #define DEFAULT_DEBUG_LOG false @@ -98,6 +98,28 @@ static bool dump_audio = false; static unsigned char audio_type = 0x00; static unsigned char previous_audio_type = 0x00; static bool fullscreen = false; +static std::string coverart_filename = ""; +static bool do_append_hostname = true; +static bool use_random_hw_addr = false; +static unsigned short display[5] = {0}, tcp[3] = {0}, udp[3] = {0}; +static bool debug_log = DEFAULT_DEBUG_LOG; + +/* 95 byte png file with a 1x1 white square (single pixel): placeholder for coverart*/ +static const unsigned char empty_image[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x25, 0xdb, 0x56, + 0xca, 0x00, 0x00, 0x00, 0x03, 0x50, 0x4c, 0x54, 0x45, 0x00, 0x00, 0x00, 0xa7, 0x7a, 0x3d, 0xda, + 0x00, 0x00, 0x00, 0x01, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x40, 0xe6, 0xd8, 0x66, 0x00, 0x00, 0x00, + 0x0a, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe2, + 0x21, 0xbc, 0x33, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; + +size_t write_coverart(const char *filename, const void *image, size_t len) { + FILE *fp = fopen(filename, "wb"); + size_t count = fwrite(image, 1, len, fp); + fclose(fp); + return count; +} + void dump_audio_to_file(unsigned char *data, int datalen, unsigned char type) { if (!audio_dumpfile && audio_type != previous_audio_type) { @@ -301,17 +323,13 @@ static void print_info (char *name) { 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("-s wxh[@r]Set display resolution [refresh_rate] default 1920x1080[@60]\n"); - printf("-o Set mirror \"overscanned\" mode on (not usually needed)\n"); + printf("-o Set display \"overscanned\" mode on (not usually needed)\n"); printf("-fs Full-screen (only with Wayland and VAAPI plugins)\n"); - printf("-fps n Set maximum allowed streaming framerate, default 30\n"); - printf("-f {H|V|I}Horizontal|Vertical flip, or both=Inversion=rotate 180 deg\n"); - printf("-r {R|L} Rotate 90 degrees Right (cw) or Left (ccw)\n"); printf("-p Use legacy ports UDP 6000:6001:7011 TCP 7000:7001:7100\n"); printf("-p n Use TCP and UDP ports n,n+1,n+2. range %d-%d\n", LOWEST_ALLOWED_PORT, HIGHEST_PORT); 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 separately\n"); - printf("-m Use random MAC address (use for concurrent UxPlay's)\n"); - printf("-t n Relaunch server if no connection existed in last n seconds\n"); + printf("-avdec Force software h264 video decoding with libav decoder\n"); printf("-vp ... Choose the GSteamer h264 parser: default \"h264parse\"\n"); printf("-vd ... Choose the GStreamer h264 decoder; default \"decodebin\"\n"); printf(" choices: (software) avdec_h264; (hardware) v4l2h264dec,\n"); @@ -327,13 +345,18 @@ static void print_info (char *name) { printf("-rpi Same as \"-v4l2\" (for RPi=Raspberry Pi).\n"); printf("-rpifb Same as \"-v4l2 -vs kmssink\" for RPi using framebuffer.\n"); printf("-rpiwl Same as \"-v4l2 -vs waylandsink\" for RPi using Wayland.\n"); - printf("-avdec Force software h264 video decoding with libav decoder\n"); printf("-as ... Choose the GStreamer audiosink; default \"autoaudiosink\"\n"); printf(" choices: pulsesink,alsasink,osssink,oss4sink,osxaudiosink\n"); printf("-as 0 (or -a) Turn audio off, streamed video only\n"); + printf("-ca In Airplay Audio (ALAC) mode, write cover-art to file \n"); printf("-reset n Reset after 3n seconds client silence (default %d, 0=never)\n", NTP_TIMEOUT_LIMIT); printf("-nc do Not Close video window when client stops mirroring\n"); printf("-FPSdata Show video-streaming performance reports sent by client.\n"); + printf("-fps n Set maximum allowed streaming framerate, default 30\n"); + printf("-f {H|V|I}Horizontal|Vertical flip, or both=Inversion=rotate 180 deg\n"); + printf("-r {R|L} Rotate 90 degrees Right (cw) or Left (ccw)\n"); + printf("-m Use random MAC address (use for concurrent UxPlay's)\n"); + printf("-t n Relaunch server if no connection existed in last n seconds\n"); printf("-vdmp [n] Dump h264 video output to \"fn.h264\"; fn=\"videodump\",change\n"); printf(" with \"-vdmp [n] filename\". If [n] is given, file fn.x.h264\n"); printf(" x=1,2,.. opens whenever a new SPS/PPS NAL arrives, and <=n\n"); @@ -467,21 +490,7 @@ static void append_hostname(std::string &server_name) { } } -int main (int argc, char *argv[]) { - std::vector server_hw_addr; - bool do_append_hostname = true; - bool use_random_hw_addr = false; - bool debug_log = DEFAULT_DEBUG_LOG; - unsigned short display[5] = {0}, tcp[3] = {0}, udp[3] = {0}; - -#ifdef SUPPRESS_AVAHI_COMPAT_WARNING - // suppress avahi_compat nag message. avahi emits a "nag" warning (once) - // if getenv("AVAHI_COMPAT_NOWARN") returns null. - static char avahi_compat_nowarn[] = "AVAHI_COMPAT_NOWARN=1"; - if (!getenv("AVAHI_COMPAT_NOWARN")) putenv(avahi_compat_nowarn); -#endif - - +void parse_arguments (int argc, char *argv[]) { // Parse arguments for (int i = 1; i < argc; i++) { std::string arg(argv[i]); @@ -659,12 +668,33 @@ int main (int argc, char *argv[]) { audio_dumpfile_name.append(argv[i]); } } + } else if (arg == "-ca" ) { + if (option_has_value(i, argc, arg, argv[i+1])) { + coverart_filename.erase(); + coverart_filename.append(argv[++i]); + } else { + LOGE("option -ca must be followed by a filename for cover-art output"); + exit(1); + } } else { LOGE("unknown option %s, stopping\n",argv[i]); exit(1); } } +} +int main (int argc, char *argv[]) { + std::vector server_hw_addr; + +#ifdef SUPPRESS_AVAHI_COMPAT_WARNING + // suppress avahi_compat nag message. avahi emits a "nag" warning (once) + // if getenv("AVAHI_COMPAT_NOWARN") returns null. + static char avahi_compat_nowarn[] = "AVAHI_COMPAT_NOWARN=1"; + if (!getenv("AVAHI_COMPAT_NOWARN")) putenv(avahi_compat_nowarn); +#endif + + parse_arguments (argc, argv); + if (audiosink == "0") { use_audio = false; } @@ -723,6 +753,11 @@ int main (int argc, char *argv[]) { parse_hw_addr(mac_address, server_hw_addr); mac_address.clear(); + if (coverart_filename.length()) { + LOGI("any AirPlay audio cover-art will be written to file %s",coverart_filename.c_str()); + write_coverart(coverart_filename.c_str(), (const void *) empty_image, sizeof(empty_image)); + } + connections_stopped = true; relaunch: if (start_raop_server(server_hw_addr, server_name, display, tcp, udp, debug_log)) { @@ -776,6 +811,9 @@ int main (int argc, char *argv[]) { fwrite(mark, 1, sizeof(mark), video_dumpfile); fclose(video_dumpfile); } + if (coverart_filename.length()) { + remove (coverart_filename.c_str()); + } } // Server callbacks @@ -873,12 +911,22 @@ extern "C" void audio_get_format (void *cls, unsigned char *ct, unsigned short * if (use_audio) { audio_renderer_start(ct); } + + if (coverart_filename.length()) { + write_coverart(coverart_filename.c_str(), (const void *) empty_image, sizeof(empty_image)); + } } extern "C" void video_report_size(void *cls, float *width_source, float *height_source, float *width, float *height) { video_renderer_size(width_source, height_source, width, height); } +extern "C" void audio_set_coverart(void *cls, const void *buffer, int buflen) { + if (buffer && coverart_filename.length()) { + write_coverart(coverart_filename.c_str(), buffer, buflen); + LOGI("coverart size %d written to %s", buflen, coverart_filename.c_str()); + } +} extern "C" void audio_set_metadata(void *cls, const void *buffer, int buflen) { unsigned char mark[]={ 0x00, 0x00, 0x00 }; /*daap seperator mark */ if (buflen > 4) { @@ -958,6 +1006,7 @@ int start_raop_server (std::vector hw_addr, std::string name, unsigned sho raop_cbs.audio_get_format = audio_get_format; raop_cbs.video_report_size = video_report_size; raop_cbs.audio_set_metadata = audio_set_metadata; + raop_cbs.audio_set_coverart = audio_set_coverart; /* set max number of connections = 2 */ raop = raop_init(2, &raop_cbs);