FD- / RPiPlay

An open-source AirPlay mirroring server for the Raspberry Pi. Supports iOS 9 and up.
GNU General Public License v3.0
4.91k stars 355 forks source link

extend API to allow choices for network ports, display resolution and streaming framerate #257

Closed fduncanh closed 2 years ago

fduncanh commented 2 years ago

API changes (plus an update to rpiplay.cpp to use them) are included in this pull request. The API changes are backwards-compatible. They are also used in an update to the RPiPlay fork at UxPlay at http://github.com/FDH2/UxPlay antimof/UxPlay#58 (I don't know whether the original UxPlay creator antimof will notice them, and update his UxPlay git repository)

Please view the API extensions as an "upstream contribution". I hope they can be incorporated in the canonical version of the RAOP/AirPlay library maintained on this site. (There are a number of other fixes and improvements to UxPlay in the new release, that I would be happy to contribute the RPiPlay here, if there is any interest.)

*Summary of API extensions"

The API update adds three new functions to the raop/Airplay API, to allow user requests for network ports and mirror display size to be written into the structure raop_t raop, to change the defaults when a connection is later made and comm->raop_ntp, comm->raop_rtp, and conn->raop_rtp_mirror are created. The functions are

raop_set_udp_ports(raop_t, raop,  unsigned short udp[3])
raop_set_tcp_ports(raop_t raop,  unsigned short tcp[2]) 
raop_set_display(raop_t raop,  unsigned short width, unsigned short height, unsigned short refresh_rate, unsigned short max_fps)

the behavior of the raop library is unchanged unless these are called. This will allow specific network ports opened in a firewall to be used (current rpiplay will not work if the server is behind a firewall; in my standard firewall, only the tcp ports need to be opened, the AirPlay UDP traffic is unblocked).

set_display also allows modification of four of the plist variables that the server passes to the AirPlay client. Three of these are the resolution and refresh rate width x height @ refresh rate (default 1920 x 1080 @ 60) (pixels x pixels @ Hz).

I discovered that in raop_handlers.h, the "refreshRate" plist entry had been broken when FD- converted the original binary plist (in commit https://github.com/FD-/RPiPlay/commit/83c85cf656d453d10eb293ecd2f59e916ba9f0d0#diff-40a01c0bfaecb9b77dfebf3e5c80264ffb5d3f6976da5d69f33ccbf27f12edf5 line 147 raop_handlers.h): "plist_new_real (1.0 / 60.0 )" should have been "plist_new_uint(60)" . In addition on reading the binary with plistutil, I found an entry "maxFPS" had been omited (its default is 30 fps). This is an important variable that tells the client not to stream video faster than maxFPS, and is the fourth entry I made accessible. width, height and max_fps allow important control of the streaming. (In my testing the client does not seem to care about the value of refreshRate).

(an additional plist correction: A few uints and bools with values 0 had been mixed up, according to both plistutil and direct inspection of the binary plist, where 0x08, 0x09 are boolean 0,1 and 0xa1 0x00 and 0xa1 0x01 are uint8_t 0,1.)

I also provide an update to rpiplay.cpp to use these new API features

rpiplay -tcp [n1,n2]] set two network TCP ports to be used rpiplay -udp [n1.n2.n3] set three UDP ports to be used rpiplay -s wxh@r set widthPixels heightPixels refreshRate rpiplay -fps n set maxFPS

These display-size changes are inspired by pull requests #141 and #191 , (but implemented in a perhaps cleaner way), by adding new entries (total of 14 bytes ) in struct raop_s. (however #191 's attempt to set refreshRate is broken because of the error that had been previously made in the plist)

The network-port-setting facility is inspired by pull request# #196 and FD-'s comments. there and in PR #249 , both closed.