FDH2 / UxPlay

AirPlay Unix mirroring server
GNU General Public License v3.0
1.53k stars 78 forks source link

No obvious solution to "iOS clients do play audio on client with video mirrored on server if feature bit 9 (audio support) is disabled on server" , but close video connection after 60 secs(was:Can the audio be directed to Bluetooth headphones or remain on the mobile phone? #303

Closed fduncanh closed 3 months ago

fduncanh commented 3 months ago

see https://github.com/antimof/UxPlay/issues/165 @fengzhuzhu writes:

I want to only mirror the video while keeping the audio on my phone. I achieved the desired effect by modifying the Features to "0x4003C880", but I receive a "TEARDOWN" command after one minute. Please help me how to handle this, thank you!

fduncanh commented 3 months ago

I confirmed the teardown.

You can change the Features bits easily in uxplay.cpp at line 1349. Only bit 9 needs to be off.

uxplay -d (debug) shows

raop_rtp video: now = 1717316973.380776, ntp = 1717316973.467015, latency = -0.086239, ts = 316644.787629, 00 00 00 00 
raop_rtp video: now = 1717316973.401731, ntp = 1717316973.500313, latency = -0.098582, ts = 316644.820927, 00 00 00 00 
raop_rtp video: now = 1717316973.437299, ntp = 1717316973.533640, latency = -0.096340, ts = 316644.854254, 00 00 00 00 
raop_rtp_mirror tcp socket is closed, got 0 bytes of 128 byte header   <<<<<<<<<<< client closed the TCP socket for video data
httpd receiving on socket 20  <<<<<<< client is now sending  a RTSP TEARDOWN request for the server to terminate video services
conn_request

TEARDOWN rtsp://2600:4040:a039:4900:82c1:6eff:feec:a088/15613886585693490906 RTSP/1.0
Content-Length: 69
Content-Type: application/x-apple-binary-plist
CSeq: 38
DACP-ID: 75180DCCB178B2AE
Active-Remote: 906489351
User-Agent: AirPlay/770.8.1

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>streams</key>
        <array>
                <dict>
                        <key>type</key>
                        <integer>110</integer>  <<<<< this means terminate video services
                </dict>
        </array>
</dict>
</plist>

Handling request TEARDOWN with URL rtsp://2600:4040:a039:4900:82c1:6eff:feec:a088/15613886585693490906
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>streams</key>
        <array>
                <dict>
                        <key>type</key>
                        <integer>110</integer>
                </dict>
        </array>
</dict>
</plist>

TEARDOWN request,  96=0, 110=1
raop_rtp_mirror->running is no longer true
raop_rtp_mirror exiting TCP thread
fduncanh commented 3 months ago

Yes , it seems to teardown exactly (almost ) 60 seconds (say 57 or 58 secs) after starting video. Lets confirm that. Might be that if the audio is not being received., uxplay is not sending the heartbeat signal. If so it could be fixed.

fduncanh commented 3 months ago

After almost 60 secs after the video transmission starts, the iOS client with a uxplay (where features bit 9 (support audio) is set to off) closes the TCP socket used to send video to uxplay in mirror mode (tested using a youtube video displaying on an iPad in firefox), and sends the (video) TEARDOWN (110) RTSP request to the server.

The only signals uxplay sends to the server are UDP timing signals and responses to RTSP requests from the client (such as the TEARDOWN request) on the main TCP connection. (When audio is being received UDP control port signals to request resends of missing audio packet can also occur).

There is nothing obviously different in debug traces from mirrors session with audio (features bit 9 on, no TEARDOWN) and without (features 9 bit off, TEARDOWN request sent)

Since it is the client doing this, there is no way to change this behavior except through the "features" the server advertises, or through RTSP response headers or plists it sends during SETUP, etc. (I'll check if a "keepalive" header might be needed, otherwise I have no idea why the client does this).

fduncanh commented 3 months ago

If this client-closes-raop_rtp_mirror_tcp_socket-after-1-minute_if_audio_support_is_disabled issue has a solution, this would be a good added feature for uxplay, but some reworking of the connection-closing code (which probably assumes audio conection was made) will be needed.

EDIT: tested on a completely independent implementation of airplay mirroring (apsdk, available as a demo only): same result (as expected) so this is definitely an AirPlay Protocol issue on the Client , not UxPlay coding on the server.

fduncanh commented 3 months ago

Since there seens no solution, will close this issue, but please add any solutions found here.