From: Mike Brady Date: Tue, 9 Jan 2018 17:54:24 +0000 (+0000) Subject: use max-latency and min-latency information in AirPlay ANNOUNCE packets, remove diffe... X-Git-Tag: 3.2d22~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9cfc6c475bfa1edaea361ad6dbb6462e2cb03328;p=thirdparty%2Fshairport-sync.git use max-latency and min-latency information in AirPlay ANNOUNCE packets, remove different latency settings except one fixed one --- diff --git a/common.h b/common.h index 2d1547c6..aa4633b8 100644 --- a/common.h +++ b/common.h @@ -123,9 +123,8 @@ typedef struct { int buffer_start_fill; int64_t latency; int64_t userSuppliedLatency; // overrides all other latencies -- use with caution - int64_t iTunesLatency; // supplied with --iTunesLatency option - int64_t AirPlayLatency; // supplied with --AirPlayLatency option - int64_t ForkedDaapdLatency; // supplied with --ForkedDaapdLatency option + int64_t fixedLatencyOffset; // add this to all automatic latencies supplied to get the actual total latency + // the total latency will be limited to the min and max-latency values, if supplied int daemonise; int daemonise_store_pid; // don't try to save a PID file char *piddir; diff --git a/player.h b/player.h index 0f557299..2b0a47c7 100644 --- a/player.h +++ b/player.h @@ -63,8 +63,9 @@ typedef struct { typedef struct { int connection_number; // for debug ID purposes, nothing else... - int64_t staticLatencyCorrection; // it seems iTunes needs some offset before it's more or less - // right. Odd. + int64_t minimum_latency; // set if an a=min-latency: line appears in the ANNOUNCE message; zero otherwise + int64_t maximum_latency; // set if an a=max-latency: line appears in the ANNOUNCE message; zero otherwise + #if defined(HAVE_DBUS) || defined(HAVE_MPRIS) enum session_status_type play_state; #endif diff --git a/rtp.c b/rtp.c index 64fbe6d7..c24940ca 100644 --- a/rtp.c +++ b/rtp.c @@ -226,18 +226,28 @@ void *rtp_control_receiver(void *arg) { rtp_timestamp_less_latency = monotonic_timestamp(ntohl(*((uint32_t *)&packet[4])), conn); sync_rtp_timestamp = monotonic_timestamp(ntohl(*((uint32_t *)&packet[16])), conn); - if (config.use_negotiated_latencies) { + if (config.userSuppliedLatency) { + if (config.userSuppliedLatency != config.latency) { + debug(1,"Using the user-supplied latency: %lld.",config.userSuppliedLatency); + } + config.latency = config.userSuppliedLatency; + } else { int64_t la = - sync_rtp_timestamp - rtp_timestamp_less_latency + conn->staticLatencyCorrection; + sync_rtp_timestamp - rtp_timestamp_less_latency + config.fixedLatencyOffset; + if ((conn->maximum_latency) && (conn->maximum_latencymaximum_latency; + if ((conn->minimum_latency) && (conn->minimum_latency>la)) + la = conn->minimum_latency; + if (la != config.latency) { config.latency = la; - // debug(1, - // "Using negotiated latency of %lld frames and a static latency correction of - // %lld", - // sync_rtp_timestamp - rtp_timestamp_less_latency, conn->staticLatencyCorrection); + debug(1,"New latency: %lld, sync latency: %lld, minimum latency: %lld, maximum latency: %lld, fixed offset: %lld.", + la,sync_rtp_timestamp - rtp_timestamp_less_latency,conn->minimum_latency,conn->maximum_latency,config.fixedLatencyOffset); } } + // need to clarify this. + if (packet[0] & 0x10) { // if it's a packet right after a flush or resume sync_rtp_timestamp += 352; // add frame_size -- can't see a reference to this anywhere, diff --git a/rtsp.c b/rtsp.c index fcb8a4d6..7f1769c7 100644 --- a/rtsp.c +++ b/rtsp.c @@ -3,7 +3,7 @@ * Copyright (c) James Laird 2013 * Modifications associated with audio synchronization, mutithreading and - * metadata handling copyright (c) Mike Brady 2014-2017 + * metadata handling copyright (c) Mike Brady 2014-2018 * All rights reserved. * * Permission is hereby granted, free of charge, to any person @@ -771,70 +771,7 @@ static void handle_setup(rtsp_conn_info *conn, rtsp_message *req, rtsp_message * send_metadata('ssnc', 'daid', ar, strlen(ar), req, 1); #endif } - - // This latency-setting mechanism is deprecated and will be removed. - // If no non-standard latency is chosen, automatic negotiated latency setting - // is permitted. - - // Select a static latency - // if iTunes V10 or later is detected, use the iTunes latency setting - // if AirPlay is detected, use the AirPlay latency setting - // for everything else, use the general latency setting, if given, or - // else use the default latency setting - - config.latency = -1; - - if (config.userSuppliedLatency) - config.latency = config.userSuppliedLatency; - - char *ua = msg_get_header(req, "User-Agent"); - if (ua == 0) { - debug(1, "No User-Agent string found in the SETUP message. Using latency " - "of %d frames.", - config.latency); - } else { - if (strstr(ua, "iTunes") == ua) { - int iTunesVersion = 0; - // now check it's version 10 or later - char *pp = strchr(ua, '/') + 1; - if (pp) - iTunesVersion = atoi(pp); - else - debug(2, "iTunes Version Number not found."); - if (iTunesVersion >= 10) { - debug(1, "User-Agent is iTunes 10 or better, (actual version is %d); " - "selecting the iTunes " - "latency of %d frames.", - iTunesVersion, config.iTunesLatency); - config.latency = config.iTunesLatency; - conn->staticLatencyCorrection = 11025; - } - } else if (strstr(ua, "AirPlay") == ua) { - debug(2, "User-Agent is AirPlay; selecting the AirPlay latency of %d frames.", - config.AirPlayLatency); - config.latency = config.AirPlayLatency; - } else if (strstr(ua, "forked-daapd") == ua) { - debug(2, "User-Agent is forked-daapd; selecting the forked-daapd latency " - "of %d frames.", - config.ForkedDaapdLatency); - config.latency = config.ForkedDaapdLatency; - conn->staticLatencyCorrection = 11025; - } else if (strstr(ua, "Airfoil") == ua) { - debug(2, "User-Agent is Airfoil"); - conn->staticLatencyCorrection = 11025; - } else { - debug(2, "Unrecognised User-Agent. Using latency of %d frames.", config.latency); - } - } - - if (config.latency == -1) { - // this means that no static latency was set, so we'll allow it to be set - // dynamically - config.latency = 88198; // to be sure, to be sure -- make it slighty - // different from the default to ensure we get a - // debug message when set to 88200 - config.use_negotiated_latencies = 1; - } + char *hdr = msg_get_header(req, "Transport"); if (!hdr) goto error; @@ -1541,13 +1478,13 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag } if (pminlatency) { - int minl = atoi(pminlatency); - debug(1,"Minimum latency %d specified",minl); + conn->minimum_latency = atoi(pminlatency); + debug(1,"Minimum latency %d specified",conn->minimum_latency); } if (pmaxlatency) { - int maxl = atoi(pmaxlatency); - debug(1,"Maximum latency %d specified",maxl); + conn->maximum_latency = atoi(pmaxlatency); + debug(1,"Maximum latency %d specified",conn->maximum_latency); } if ((paesiv == NULL) && (prsaaeskey == NULL)) { diff --git a/shairport.c b/shairport.c index ecabd075..e14830eb 100644 --- a/shairport.c +++ b/shairport.c @@ -279,18 +279,9 @@ void usage(char *progname) { printf(" -v, --verbose -v print debug information; -vv more; -vvv lots.\n"); printf(" -p, --port=PORT set RTSP listening port.\n"); printf(" -a, --name=NAME set advertised name.\n"); - // printf(" -A, --AirPlayLatency=FRAMES [Deprecated] Set the latency for audio sent from an " - // "AirPlay device.\n"); - // printf(" The default is to set it automatically.\n"); - // printf(" -i, --iTunesLatency=FRAMES [Deprecated] Set the latency for audio sent from iTunes - // " - // "10 or later.\n"); - // printf(" The default is to set it automatically.\n"); printf(" -L, --latency=FRAMES [Deprecated] Set the latency for audio sent from an unknown " "device.\n"); printf(" The default is to set it automatically.\n"); - printf(" --forkedDaapdLatency=FRAMES [Deprecated] Set the latency for audio sent from " - "forked-daapd.\n"); printf(" The default is to set it automatically.\n"); printf(" -S, --stuffing=MODE set how to adjust current latency to match desired latency, " "where \n"); @@ -369,9 +360,6 @@ int parse_options(int argc, char **argv) { {"wait-cmd", 'w', POPT_ARG_NONE, &config.cmd_blocking, 0, NULL}, {"mdns", 'm', POPT_ARG_STRING, &config.mdns_name, 0, NULL}, {"latency", 'L', POPT_ARG_INT, &config.userSuppliedLatency, 0, NULL}, - {"AirPlayLatency", 'A', POPT_ARG_INT, &config.AirPlayLatency, 0, NULL}, - {"iTunesLatency", 'i', POPT_ARG_INT, &config.iTunesLatency, 0, NULL}, - {"forkedDaapdLatency", 'f', POPT_ARG_INT, &config.ForkedDaapdLatency, 0, NULL}, {"stuffing", 'S', POPT_ARG_STRING, &stuffing, 'S', NULL}, {"resync", 'r', POPT_ARG_INT, &fResyncthreshold, 0, NULL}, {"timeout", 't', POPT_ARG_INT, &config.timeout, 't', NULL}, @@ -408,15 +396,15 @@ int parse_options(int argc, char **argv) { inform("Warning: the option -R or --reconnectToOutput is deprecated."); break; case 'A': - inform("Warning: the option -A or --AirPlayLatency is deprecated. This setting is now " + inform("Warning: the option -A or --AirPlayLatency is deprecated and ignored. This setting is now " "automatically received from the AirPlay device."); break; case 'i': - inform("Warning: the option -i or --iTunesLatency is deprecated. This setting is now " + inform("Warning: the option -i or --iTunesLatency is deprecated and ignored. This setting is now " "automatically received from iTunes"); break; case 'f': - inform("Warning: the option --forkedDaapdLatency is deprecated. This setting is now " + inform("Warning: the option --forkedDaapdLatency is deprecated and ignored. This setting is now " "automatically received from forkedDaapd"); break; case 'r': @@ -447,6 +435,7 @@ int parse_options(int argc, char **argv) { config.audio_backend_silent_lead_in_time = -1.0; // flag to indicate it has not been set config.airplay_volume = -18.0; // if no volume is ever set, default to initial default value if // nothing else comes in first. + config.fixedLatencyOffset = 11025; // this sounds like it works properly. config_setting_t *setting; const char *str = 0; @@ -710,18 +699,6 @@ int parse_options(int argc, char **argv) { if (config_lookup_int(config.cfg, "latencies.default", &value)) config.userSuppliedLatency = value; - /* Get the itunes latency. Deprecated! */ - if (config_lookup_int(config.cfg, "latencies.itunes", &value)) - config.iTunesLatency = value; - - /* Get the AirPlay latency. Deprecated! */ - if (config_lookup_int(config.cfg, "latencies.airplay", &value)) - config.AirPlayLatency = value; - - /* Get the forkedDaapd latency. Deprecated! */ - if (config_lookup_int(config.cfg, "latencies.forkedDaapd", &value)) - config.ForkedDaapdLatency = value; - #ifdef CONFIG_METADATA /* Get the metadata setting. */ if (config_lookup_string(config.cfg, "metadata.enabled", &str)) { @@ -1135,14 +1112,6 @@ int main(int argc, char **argv) { config.latency = -1; // -1 means not set. 88200 works well. This is also reset in rtsp.c when play // is about to start config.userSuppliedLatency = 0; // zero means none supplied - config.iTunesLatency = - -1; // -1 means not supplied. 99400 seems to work pretty well for iTunes from Version 10 (?) - // upwards-- two left-ear headphones, one from the iMac jack, one - // from an NSLU2 running a cheap "3D Sound" USB Soundcard - config.AirPlayLatency = - -1; // -1 means not set. 88200 seems to work well for AirPlay -- Syncs sound and - // vision on AppleTV, but also used for iPhone/iPod/iPad sources - config.ForkedDaapdLatency = -1; // -1 means not set. 99400 seems to be right config.resyncthreshold = 0.05; // 50 ms config.timeout = 120; // this number of seconds to wait for [more] audio before switching to idle. config.tolerance = @@ -1374,55 +1343,12 @@ int main(int argc, char **argv) { } /* Mess around with the latency options */ - // Basically, we used to rely on static latencies -- 99400 for iTunes 10 or later and forkedDaapd, - // 88200 for everything else - // Nowadays we allow the source to set the latency, which works out at 99651 for iTunes 10 and - // forkedDaapd and 88220 for everything else - // What we want to do here is allow the source to set the latency unless the user has specified an - // non-standard latency. - // If the user has specified a standard latency, we suggest to them to stop doing it. + // Basically, we expect the source to set the latency and add a fixed offset of 11025 frames to it, which sounds right + // If this latency is outside the max and min latensies that may be set by the source, clamp it to fit. + // If they specify a non-standard latency, we suggest the user to use the // audio_backend_latency_offset instead. - if (config.AirPlayLatency != -1) { - if (config.AirPlayLatency == 88200) { - inform("It is not necessary to set the AirPlay latency to 88200 -- you should remove this " - "setting or configuration option, as it is deprecated."); - config.AirPlayLatency = -1; - } else { - inform("The AirPlay latency setting is deprecated, as Shairport Sync can now get the correct " - "latency from the source."); - inform("Please remove this setting and use the relevant audio_backend_latency_offset " - "setting, if necessary, to compensate for delays elsewhere."); - } - } - - if (config.iTunesLatency != -1) { - if (config.iTunesLatency == 99400) { - inform("It is not necessary to set the iTunes latency to 99400 -- you should remove this " - "setting or configuration option, as it is deprecated and ignored."); - config.iTunesLatency = -1; - } else { - inform("The iTunes latency setting is deprecated, as Shairport Sync can now get the correct " - "latency from the source."); - inform("Please remove this setting and use the relevant audio_backend_latency_offset " - "setting, if necessary, to compensate for delays elsewhere."); - } - } - - if (config.ForkedDaapdLatency != -1) { - if (config.ForkedDaapdLatency == 99400) { - inform("It is not necessary to set the forkedDaapd latency to 99400 -- you should remove " - "this setting or configuration option, as it is deprecated and ignored."); - config.ForkedDaapdLatency = -1; - } else { - inform("The forkedDaapd latency setting is deprecated, as Shairport Sync can now get the " - "correct latency from the source."); - inform("Please remove this setting and use the relevant audio_backend_latency_offset " - "setting, if necessary, to compensate for delays elsewhere."); - } - } - if (config.userSuppliedLatency) { inform("The default latency setting is deprecated, as Shairport Sync can now get the correct " "latency from the source."); @@ -1455,9 +1381,6 @@ int main(int argc, char **argv) { debug(1, "on-start returns output is %d.", config.cmd_start_returns_output); debug(1, "mdns backend \"%s\".", config.mdns_name); debug(2, "userSuppliedLatency is %d.", config.userSuppliedLatency); - debug(2, "AirPlayLatency is %d.", config.AirPlayLatency); - debug(2, "iTunesLatency is %d.", config.iTunesLatency); - debug(2, "forkedDaapdLatency is %d.", config.ForkedDaapdLatency); debug(1, "stuffing option is \"%d\" (0-basic, 1-soxr).", config.packet_stuffing); debug(1, "resync time is %f seconds.", config.resyncthreshold); debug(1, "allow a session to be interrupted: %d.", config.allow_session_interruption);