Skip to content

[Problem]: Buffered AirPlay 2 latency offset is calculated before input sample rate is known #2252

Description

@prhodey

What happened?

On Shairport Sync 5.2.1 in AirPlay 2 mode, changing audio_backend_latency_offset_in_seconds did not reliably produce the requested timing change for buffered 48 kHz AAC streams.

I tested offsets of -0.250 and +0.250 seconds. I expected these to shift the RTP anchor by -12,000 and +12,000 frames respectively at 48,000 frames/sec.

The apparent cause is in handle_setrateanchori():

  int32_t added_latency =
      (int32_t)(config.audio_backend_latency_offset * conn->input_rate);

For buffered stream type 103, SETRATEANCHORI can arrive before the first encoded audio block. At that point conn->input_rate has not necessarily been established by prepare_decoding_chain().

Observed results before the fix:

  • In one session conn->input_rate was still zero, so the configured offset produced no RTP-anchor adjustment.

  • In another 48 kHz session it contained a stale 44,100 value, producing 11,025 frames for 250 ms instead of 12,000.

  • The first audio block later changed conn->input_rate to 48,000, after the
    anchor had already been processed.

Steps to reproduce:

  1. Build upstream 5.2.1 with AirPlay 2 and ALSA.
  2. Enable diagnostic verbosity 2.
  3. Play a buffered AAC/F24/48 kHz AirPlay 2 stream from an Apple TV.
  4. Set audio_backend_latency_offset_in_seconds to -0.250, then +0.250, restarting Shairport Sync between tests.
  5. Observe that SETRATEANCHORI is handled before the log showing conn->input_rate being set to 48,000.

I tested a fix that reads audioFormatIndex during buffered stream SETUP, maps it to the initial SSRC format, and sets conn->input_rate before SETRATEANCHORI is received. The actual packet format remains authoritative and can update the rate later.

With that change, the same tests consistently produced the expected ±12,000 frame adjustments.

Tested patch and commit:
prhodey@30812cd

Comparison against upstream 5.2.1:
prhodey/shairport-sync@5.2.1...multiroom-5.2.2

Relevant log output

Unpatched 5.2.1 — SETRATEANCHORI precedes discovery of the 48 kHz rate:

22:49:51 "rtsp.c:1411" Connection 1: SETRATEANCHORI ...
22:49:51 "rtsp.c:1473" Connection 1: SETRATEANCHORI Start playing.
22:49:52 "player.c:1141" Connection 1: set conn->input_rate: 48000.

A session where a stale 44.1 kHz rate was present:

22:53:28 "player.c:1141" Connection 1: set conn->input_rate: 44100.
22:53:28 "rtsp.c:1411" Connection 1: SETRATEANCHORI ...
22:53:28 "rtsp.c:1473" Connection 1: SETRATEANCHORI Start playing.
22:53:29 "player.c:1141" Connection 1: set conn->input_rate: 48000.

Patched test with -250 ms:
rtsp.c:2939" Connection 1: set initial buffered input rate to 48000 from audioFormatIndex 23 (AAC/48000/F24/2). 

rtsp.c:1457" Connection 1: buffered latency offset -0.250000 seconds at 48000 FPS is -12000 frames; raw anchor 232634705, adjusted anchor 232646705.

Patched test with +250 ms:
rtsp.c:2939" Connection 1: set initial buffered input rate to 48000 from audioFormatIndex 23 (AAC/48000/F24/2).
rtsp.c:1457" Connection 1: buffered latency offset 0.250000 seconds at 48000 FPS is 12000 frames; raw anchor 233388942, adjusted anchor 233376942.

System Information.

Raspberry Pi 4 Model B Rev 1.5
Debian GNU/Linux 13 (trixie)
Linux 6.18.39+rpt-rpi-v8, aarch64

Output:
USB-C to 3.5mm Headphone Jack Adapter
ALSA USB Audio
No PulseAudio or PipeWire

Configuration Information.

Original tested version:
5.2.1-AirPlay2-smi10-OpenSSL-Avahi-ALSA-soxr-metadata-mqtt-sysconfdir:/etc

NQPTP:
Version 1.2.8, shared-memory interface smi10

Relevant configuration:

  general = {
      output_backend = "alsa";
      audio_backend_latency_offset_in_seconds = -0.250;
  };

  alsa = {
      output_device = "softvol_boost";
  };

  Build options:

  ./configure --sysconfdir=/etc \
      --with-alsa \
      --with-soxr \
      --with-avahi \
      --with-ssl=openssl \
      --with-systemd-startup \
      --with-airplay-2 \
      --with-metadata \
      --with-mqtt-client

PulseAudio or PipeWire installed?

  • Check if your system uses a Sound Server.

How did you install Shairport Sync?

Built from source

Check previous issues

  • Confirm

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions