Closed hfujita closed 9 years ago
I think I figured out what happens (the same hang happens with mplayer, hitting pause/resume a few times sometimes fixes it). It seems there's a race condition on corking/uncorking. When seeking, players apparently pause/resume sound playback using pa_stream_cork(.. true|false...)
The pause causes raop-sink.c to receive a PA_SINK_MESSAGE_SET_STATE message setting the sink state to PA_SINK_IDLE. It then triggers a pa_raop_client_flush(), which is a FLUSH command sent asynchronously to the RAOP server, and returns.
The RAOP server then sends back its ack and it arrives in raop-client.c:rtsp_stream_cb() as a STATE_FLUSH.
Then, the resume command causes raop-sink.c to receive a PA_SINK_MESSAGE_SET_STATE message setting the sink state to PA_SINK_RUNNING. It then sets the stream up again.
Using a gstreamer-based player, for example totem, the debug log looks like this: D: [raop-sink-[192.168.1.48]:1026] sink-input.c: Requesting rewind due to corking D: [raop-sink-[192.168.1.48]:1026] sink-input.c: Have to rewind 8 bytes on implementor. D: [raop-sink-[192.168.1.48]:1026] raop-sink.c: RAOP: IDLE D: [raop-sink-[192.168.1.48]:1026] rtsp_client.c: Sending command: FLUSH D: [lt-pulseaudio] module-suspend-on-idle.c: Sink raop_output.N-30.local becomes idle, timeout in 5 seconds. D: [lt-pulseaudio] rtsp_client.c: Full response received. Dispatching D: [lt-pulseaudio] raop-client.c: RAOP: FLUSHED D: [raop-sink-[192.168.1.48]:1026] protocol-native.c: Requesting rewind due to rewrite. D: [raop-sink-[192.168.1.48]:1026] sink-input.c: Requesting rewind due to uncorking D: [lt-pulseaudio] module-suspend-on-idle.c: Sink raop_output.N-30.local becomes busy, resuming. D: [raop-sink-[192.168.1.48]:1026] raop-sink.c: RAOP: RUNNING
But using mplayer, the cork/uncork happens too fast and the RUNNING state command is issued before the FLUSH is complete:
D: [raop-sink-[192.168.1.48]:1026] sink-input.c: Requesting rewind due to corking D: [raop-sink-[192.168.1.48]:1026] sink-input.c: Have to rewind 8 bytes on implementor. D: [raop-sink-[192.168.1.48]:1026] raop-sink.c: RAOP: IDLE D: [raop-sink-[192.168.1.48]:1026] rtsp_client.c: Sending command: FLUSH D: [lt-pulseaudio] module-suspend-on-idle.c: Sink raop_output.N-30.local becomes idle, timeout in 5 seconds. D: [raop-sink-[192.168.1.48]:1026] sink-input.c: Requesting rewind due to uncorking D: [lt-pulseaudio] module-suspend-on-idle.c: Sink raop_output.N-30.local becomes busy, resuming. D: [raop-sink-[192.168.1.48]:1026] raop-sink.c: RAOP: RUNNING D: [lt-pulseaudio] rtsp_client.c: Full response received. Dispatching D: [lt-pulseaudio] raop-client.c: RAOP: FLUSHED D: [raop-sink-[192.168.1.48]:1026] protocol-native.c: Requesting rewind due to end of underrun.
But I have no idea how to fix that.
Removing the handling of PA_SINK_IDLE command fixes the hang, although of course, the audio continues to play until end of buffer, and it's stupid : http://colino.net/tmp/stupid_pa_fix_for_issue_31.patch
@colinleroy Thanks Colin, this is really helpful!
How about setting c->is_recording = false when issuing the flush command? I implemented this idea, and it worked for me (mpv/clementine + Android Hi-Fi). Patch: https://github.com/hfujita/pulseaudio-raop2/commit/5a88dbedadb569b2b38bbee45c40fe5c2085b590
Wow, the fix is so simple :-) I think I was too tired to even think of it by the time I figured out the race. It also works, beautifully, with mplayer.
@colinleroy Thank you for testing! I pushed the patch (with a slight modification in the description) to the hf/raop2-v2-v5.99.1
branch.
Closed, as the fix has been confirmed. http://lists.freedesktop.org/archives/pulseaudio-discuss/2015-January/022890.html
Reported at http://lists.freedesktop.org/archives/pulseaudio-discuss/2014-November/022467.html