|
| 1 | +The ALSA API can provide two different system timestamps: |
| 2 | + |
| 3 | +- Trigger_tstamp is the system time snapshot taken when the .trigger |
| 4 | +callback is invoked. This snapshot is taken by the ALSA core in the |
| 5 | +general case, but specific hardware may have synchronization |
| 6 | +capabilities or conversely may only be able to provide a correct |
| 7 | +estimate with a delay. In the latter two cases, the low-level driver |
| 8 | +is responsible for updating the trigger_tstamp at the most appropriate |
| 9 | +and precise moment. Applications should not rely solely on the first |
| 10 | +trigger_tstamp but update their internal calculations if the driver |
| 11 | +provides a refined estimate with a delay. |
| 12 | + |
| 13 | +- tstamp is the current system timestamp updated during the last |
| 14 | +event or application query. |
| 15 | +The difference (tstamp - trigger_tstamp) defines the elapsed time. |
| 16 | + |
| 17 | +The ALSA API provides reports two basic pieces of information, avail |
| 18 | +and delay, which combined with the trigger and current system |
| 19 | +timestamps allow for applications to keep track of the 'fullness' of |
| 20 | +the ring buffer and the amount of queued samples. |
| 21 | + |
| 22 | +The use of these different pointers and time information depends on |
| 23 | +the application needs: |
| 24 | + |
| 25 | +- 'avail' reports how much can be written in the ring buffer |
| 26 | +- 'delay' reports the time it will take to hear a new sample after all |
| 27 | +queued samples have been played out. |
| 28 | + |
| 29 | +When timestamps are enabled, the avail/delay information is reported |
| 30 | +along with a snapshot of system time. Applications can select from |
| 31 | +CLOCK_REALTIME (NTP corrections including going backwards), |
| 32 | +CLOCK_MONOTONIC (NTP corrections but never going backwards), |
| 33 | +CLOCK_MONOTIC_RAW (without NTP corrections) and change the mode |
| 34 | +dynamically with sw_params |
| 35 | + |
| 36 | + |
| 37 | +The ALSA API also provide an audio_tstamp which reflects the passage |
| 38 | +of time as measured by different components of audio hardware. In |
| 39 | +ascii-art, this could be represented as follows (for the playback |
| 40 | +case): |
| 41 | + |
| 42 | + |
| 43 | +--------------------------------------------------------------> time |
| 44 | + ^ ^ ^ ^ ^ |
| 45 | + | | | | | |
| 46 | + analog link dma app FullBuffer |
| 47 | + time time time time time |
| 48 | + | | | | | |
| 49 | + |< codec delay >|<--hw delay-->|<queued samples>|<---avail->| |
| 50 | + |<----------------- delay---------------------->| | |
| 51 | + |<----ring buffer length---->| |
| 52 | + |
| 53 | +The analog time is taken at the last stage of the playback, as close |
| 54 | +as possible to the actual transducer |
| 55 | + |
| 56 | +The link time is taken at the output of the SOC/chipset as the samples |
| 57 | +are pushed on a link. The link time can be directly measured if |
| 58 | +supported in hardware by sample counters or wallclocks (e.g. with |
| 59 | +HDAudio 24MHz or PTP clock for networked solutions) or indirectly |
| 60 | +estimated (e.g. with the frame counter in USB). |
| 61 | + |
| 62 | +The DMA time is measured using counters - typically the least reliable |
| 63 | +of all measurements due to the bursty natured of DMA transfers. |
| 64 | + |
| 65 | +The app time corresponds to the time tracked by an application after |
| 66 | +writing in the ring buffer. |
| 67 | + |
| 68 | +The application can query what the hardware supports, define which |
| 69 | +audio time it wants reported by selecting the relevant settings in |
| 70 | +audio_tstamp_config fields, get an estimate of the timestamp |
| 71 | +accuracy. It can also request the delay-to-analog be included in the |
| 72 | +measurement. Direct access to the link time is very interesting on |
| 73 | +platforms that provide an embedded DSP; measuring directly the link |
| 74 | +time with dedicated hardware, possibly synchronized with system time, |
| 75 | +removes the need to keep track of internal DSP processing times and |
| 76 | +latency. |
| 77 | + |
| 78 | +In case the application requests an audio tstamp that is not supported |
| 79 | +in hardware/low-level driver, the type is overridden as DEFAULT and the |
| 80 | +timestamp will report the DMA time based on the hw_pointer value. |
| 81 | + |
| 82 | +For backwards compatibility with previous implementations that did not |
| 83 | +provide timestamp selection, with a zero-valued COMPAT timestamp type |
| 84 | +the results will default to the HDAudio wall clock for playback |
| 85 | +streams and to the DMA time (hw_ptr) in all other cases. |
| 86 | + |
| 87 | +The audio timestamp accuracy can be returned to user-space, so that |
| 88 | +appropriate decisions are made: |
| 89 | + |
| 90 | +- for dma time (default), the granularity of the transfers can be |
| 91 | + inferred from the steps between updates and in turn provide |
| 92 | + information on how much the application pointer can be rewound |
| 93 | + safely. |
| 94 | + |
| 95 | +- the link time can be used to track long-term drifts between audio |
| 96 | + and system time using the (tstamp-trigger_tstamp)/audio_tstamp |
| 97 | + ratio, the precision helps define how much smoothing/low-pass |
| 98 | + filtering is required. The link time can be either reset on startup |
| 99 | + or reported as is (the latter being useful to compare progress of |
| 100 | + different streams - but may require the wallclock to be always |
| 101 | + running and not wrap-around during idle periods). If supported in |
| 102 | + hardware, the absolute link time could also be used to define a |
| 103 | + precise start time (patches WIP) |
| 104 | + |
| 105 | +- including the delay in the audio timestamp may |
| 106 | + counter-intuitively not increase the precision of timestamps, e.g. if a |
| 107 | + codec includes variable-latency DSP processing or a chain of |
| 108 | + hardware components the delay is typically not known with precision. |
| 109 | + |
| 110 | +The accuracy is reported in nanosecond units (using an unsigned 32-bit |
| 111 | +word), which gives a max precision of 4.29s, more than enough for |
| 112 | +audio applications... |
| 113 | + |
| 114 | +Due to the varied nature of timestamping needs, even for a single |
| 115 | +application, the audio_tstamp_config can be changed dynamically. In |
| 116 | +the STATUS ioctl, the parameters are read-only and do not allow for |
| 117 | +any application selection. To work around this limitation without |
| 118 | +impacting legacy applications, a new STATUS_EXT ioctl is introduced |
| 119 | +with read/write parameters. ALSA-lib will be modified to make use of |
| 120 | +STATUS_EXT and effectively deprecate STATUS. |
| 121 | + |
| 122 | +The ALSA API only allows for a single audio timestamp to be reported |
| 123 | +at a time. This is a conscious design decision, reading the audio |
| 124 | +timestamps from hardware registers or from IPC takes time, the more |
| 125 | +timestamps are read the more imprecise the combined measurements |
| 126 | +are. To avoid any interpretation issues, a single (system, audio) |
| 127 | +timestamp is reported. Applications that need different timestamps |
| 128 | +will be required to issue multiple queries and perform an |
| 129 | +interpolation of the results |
| 130 | + |
| 131 | +In some hardware-specific configuration, the system timestamp is |
| 132 | +latched by a low-level audio subsytem, and the information provided |
| 133 | +back to the driver. Due to potential delays in the communication with |
| 134 | +the hardware, there is a risk of misalignment with the avail and delay |
| 135 | +information. To make sure applications are not confused, a |
| 136 | +driver_timestamp field is added in the snd_pcm_status structure; this |
| 137 | +timestamp shows when the information is put together by the driver |
| 138 | +before returning from the STATUS and STATUS_EXT ioctl. in most cases |
| 139 | +this driver_timestamp will be identical to the regular system tstamp. |
| 140 | + |
| 141 | +Examples of typestamping with HDaudio: |
| 142 | + |
| 143 | +1. DMA timestamp, no compensation for DMA+analog delay |
| 144 | +$ ./audio_time -p --ts_type=1 |
| 145 | +playback: systime: 341121338 nsec, audio time 342000000 nsec, systime delta -878662 |
| 146 | +playback: systime: 426236663 nsec, audio time 427187500 nsec, systime delta -950837 |
| 147 | +playback: systime: 597080580 nsec, audio time 598000000 nsec, systime delta -919420 |
| 148 | +playback: systime: 682059782 nsec, audio time 683020833 nsec, systime delta -961051 |
| 149 | +playback: systime: 852896415 nsec, audio time 853854166 nsec, systime delta -957751 |
| 150 | +playback: systime: 937903344 nsec, audio time 938854166 nsec, systime delta -950822 |
| 151 | + |
| 152 | +2. DMA timestamp, compensation for DMA+analog delay |
| 153 | +$ ./audio_time -p --ts_type=1 -d |
| 154 | +playback: systime: 341053347 nsec, audio time 341062500 nsec, systime delta -9153 |
| 155 | +playback: systime: 426072447 nsec, audio time 426062500 nsec, systime delta 9947 |
| 156 | +playback: systime: 596899518 nsec, audio time 596895833 nsec, systime delta 3685 |
| 157 | +playback: systime: 681915317 nsec, audio time 681916666 nsec, systime delta -1349 |
| 158 | +playback: systime: 852741306 nsec, audio time 852750000 nsec, systime delta -8694 |
| 159 | + |
| 160 | +3. link timestamp, compensation for DMA+analog delay |
| 161 | +$ ./audio_time -p --ts_type=2 -d |
| 162 | +playback: systime: 341060004 nsec, audio time 341062791 nsec, systime delta -2787 |
| 163 | +playback: systime: 426242074 nsec, audio time 426244875 nsec, systime delta -2801 |
| 164 | +playback: systime: 597080992 nsec, audio time 597084583 nsec, systime delta -3591 |
| 165 | +playback: systime: 682084512 nsec, audio time 682088291 nsec, systime delta -3779 |
| 166 | +playback: systime: 852936229 nsec, audio time 852940916 nsec, systime delta -4687 |
| 167 | +playback: systime: 938107562 nsec, audio time 938112708 nsec, systime delta -5146 |
| 168 | + |
| 169 | +Example 1 shows that the timestamp at the DMA level is close to 1ms |
| 170 | +ahead of the actual playback time (as a side time this sort of |
| 171 | +measurement can help define rewind safeguards). Compensating for the |
| 172 | +DMA-link delay in example 2 helps remove the hardware buffering abut |
| 173 | +the information is still very jittery, with up to one sample of |
| 174 | +error. In example 3 where the timestamps are measured with the link |
| 175 | +wallclock, the timestamps show a monotonic behavior and a lower |
| 176 | +dispersion. |
| 177 | + |
| 178 | +Example 3 and 4 are with USB audio class. Example 3 shows a high |
| 179 | +offset between audio time and system time due to buffering. Example 4 |
| 180 | +shows how compensating for the delay exposes a 1ms accuracy (due to |
| 181 | +the use of the frame counter by the driver) |
| 182 | + |
| 183 | +Example 3: DMA timestamp, no compensation for delay, delta of ~5ms |
| 184 | +$ ./audio_time -p -Dhw:1 -t1 |
| 185 | +playback: systime: 120174019 nsec, audio time 125000000 nsec, systime delta -4825981 |
| 186 | +playback: systime: 245041136 nsec, audio time 250000000 nsec, systime delta -4958864 |
| 187 | +playback: systime: 370106088 nsec, audio time 375000000 nsec, systime delta -4893912 |
| 188 | +playback: systime: 495040065 nsec, audio time 500000000 nsec, systime delta -4959935 |
| 189 | +playback: systime: 620038179 nsec, audio time 625000000 nsec, systime delta -4961821 |
| 190 | +playback: systime: 745087741 nsec, audio time 750000000 nsec, systime delta -4912259 |
| 191 | +playback: systime: 870037336 nsec, audio time 875000000 nsec, systime delta -4962664 |
| 192 | + |
| 193 | +Example 4: DMA timestamp, compensation for delay, delay of ~1ms |
| 194 | +$ ./audio_time -p -Dhw:1 -t1 -d |
| 195 | +playback: systime: 120190520 nsec, audio time 120000000 nsec, systime delta 190520 |
| 196 | +playback: systime: 245036740 nsec, audio time 244000000 nsec, systime delta 1036740 |
| 197 | +playback: systime: 370034081 nsec, audio time 369000000 nsec, systime delta 1034081 |
| 198 | +playback: systime: 495159907 nsec, audio time 494000000 nsec, systime delta 1159907 |
| 199 | +playback: systime: 620098824 nsec, audio time 619000000 nsec, systime delta 1098824 |
| 200 | +playback: systime: 745031847 nsec, audio time 744000000 nsec, systime delta 1031847 |
0 commit comments