162306a36Sopenharmony_ci===================== 262306a36Sopenharmony_ciALSA PCM Timestamping 362306a36Sopenharmony_ci===================== 462306a36Sopenharmony_ci 562306a36Sopenharmony_ciThe ALSA API can provide two different system timestamps: 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci- Trigger_tstamp is the system time snapshot taken when the .trigger 862306a36Sopenharmony_ci callback is invoked. This snapshot is taken by the ALSA core in the 962306a36Sopenharmony_ci general case, but specific hardware may have synchronization 1062306a36Sopenharmony_ci capabilities or conversely may only be able to provide a correct 1162306a36Sopenharmony_ci estimate with a delay. In the latter two cases, the low-level driver 1262306a36Sopenharmony_ci is responsible for updating the trigger_tstamp at the most appropriate 1362306a36Sopenharmony_ci and precise moment. Applications should not rely solely on the first 1462306a36Sopenharmony_ci trigger_tstamp but update their internal calculations if the driver 1562306a36Sopenharmony_ci provides a refined estimate with a delay. 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci- tstamp is the current system timestamp updated during the last 1862306a36Sopenharmony_ci event or application query. 1962306a36Sopenharmony_ci The difference (tstamp - trigger_tstamp) defines the elapsed time. 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciThe ALSA API provides two basic pieces of information, avail 2262306a36Sopenharmony_ciand delay, which combined with the trigger and current system 2362306a36Sopenharmony_citimestamps allow for applications to keep track of the 'fullness' of 2462306a36Sopenharmony_cithe ring buffer and the amount of queued samples. 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ciThe use of these different pointers and time information depends on 2762306a36Sopenharmony_cithe application needs: 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci- ``avail`` reports how much can be written in the ring buffer 3062306a36Sopenharmony_ci- ``delay`` reports the time it will take to hear a new sample after all 3162306a36Sopenharmony_ci queued samples have been played out. 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciWhen timestamps are enabled, the avail/delay information is reported 3462306a36Sopenharmony_cialong with a snapshot of system time. Applications can select from 3562306a36Sopenharmony_ci``CLOCK_REALTIME`` (NTP corrections including going backwards), 3662306a36Sopenharmony_ci``CLOCK_MONOTONIC`` (NTP corrections but never going backwards), 3762306a36Sopenharmony_ci``CLOCK_MONOTIC_RAW`` (without NTP corrections) and change the mode 3862306a36Sopenharmony_cidynamically with sw_params 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ciThe ALSA API also provide an audio_tstamp which reflects the passage 4262306a36Sopenharmony_ciof time as measured by different components of audio hardware. In 4362306a36Sopenharmony_ciascii-art, this could be represented as follows (for the playback 4462306a36Sopenharmony_cicase): 4562306a36Sopenharmony_ci:: 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci --------------------------------------------------------------> time 4862306a36Sopenharmony_ci ^ ^ ^ ^ ^ 4962306a36Sopenharmony_ci | | | | | 5062306a36Sopenharmony_ci analog link dma app FullBuffer 5162306a36Sopenharmony_ci time time time time time 5262306a36Sopenharmony_ci | | | | | 5362306a36Sopenharmony_ci |< codec delay >|<--hw delay-->|<queued samples>|<---avail->| 5462306a36Sopenharmony_ci |<----------------- delay---------------------->| | 5562306a36Sopenharmony_ci |<----ring buffer length---->| 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ciThe analog time is taken at the last stage of the playback, as close 5962306a36Sopenharmony_cias possible to the actual transducer 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ciThe link time is taken at the output of the SoC/chipset as the samples 6262306a36Sopenharmony_ciare pushed on a link. The link time can be directly measured if 6362306a36Sopenharmony_cisupported in hardware by sample counters or wallclocks (e.g. with 6462306a36Sopenharmony_ciHDAudio 24MHz or PTP clock for networked solutions) or indirectly 6562306a36Sopenharmony_ciestimated (e.g. with the frame counter in USB). 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ciThe DMA time is measured using counters - typically the least reliable 6862306a36Sopenharmony_ciof all measurements due to the bursty nature of DMA transfers. 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ciThe app time corresponds to the time tracked by an application after 7162306a36Sopenharmony_ciwriting in the ring buffer. 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciThe application can query the hardware capabilities, define which 7462306a36Sopenharmony_ciaudio time it wants reported by selecting the relevant settings in 7562306a36Sopenharmony_ciaudio_tstamp_config fields, thus get an estimate of the timestamp 7662306a36Sopenharmony_ciaccuracy. It can also request the delay-to-analog be included in the 7762306a36Sopenharmony_cimeasurement. Direct access to the link time is very interesting on 7862306a36Sopenharmony_ciplatforms that provide an embedded DSP; measuring directly the link 7962306a36Sopenharmony_citime with dedicated hardware, possibly synchronized with system time, 8062306a36Sopenharmony_ciremoves the need to keep track of internal DSP processing times and 8162306a36Sopenharmony_cilatency. 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ciIn case the application requests an audio tstamp that is not supported 8462306a36Sopenharmony_ciin hardware/low-level driver, the type is overridden as DEFAULT and the 8562306a36Sopenharmony_citimestamp will report the DMA time based on the hw_pointer value. 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ciFor backwards compatibility with previous implementations that did not 8862306a36Sopenharmony_ciprovide timestamp selection, with a zero-valued COMPAT timestamp type 8962306a36Sopenharmony_cithe results will default to the HDAudio wall clock for playback 9062306a36Sopenharmony_cistreams and to the DMA time (hw_ptr) in all other cases. 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciThe audio timestamp accuracy can be returned to user-space, so that 9362306a36Sopenharmony_ciappropriate decisions are made: 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci- for dma time (default), the granularity of the transfers can be 9662306a36Sopenharmony_ci inferred from the steps between updates and in turn provide 9762306a36Sopenharmony_ci information on how much the application pointer can be rewound 9862306a36Sopenharmony_ci safely. 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci- the link time can be used to track long-term drifts between audio 10162306a36Sopenharmony_ci and system time using the (tstamp-trigger_tstamp)/audio_tstamp 10262306a36Sopenharmony_ci ratio, the precision helps define how much smoothing/low-pass 10362306a36Sopenharmony_ci filtering is required. The link time can be either reset on startup 10462306a36Sopenharmony_ci or reported as is (the latter being useful to compare progress of 10562306a36Sopenharmony_ci different streams - but may require the wallclock to be always 10662306a36Sopenharmony_ci running and not wrap-around during idle periods). If supported in 10762306a36Sopenharmony_ci hardware, the absolute link time could also be used to define a 10862306a36Sopenharmony_ci precise start time (patches WIP) 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci- including the delay in the audio timestamp may 11162306a36Sopenharmony_ci counter-intuitively not increase the precision of timestamps, e.g. if a 11262306a36Sopenharmony_ci codec includes variable-latency DSP processing or a chain of 11362306a36Sopenharmony_ci hardware components the delay is typically not known with precision. 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciThe accuracy is reported in nanosecond units (using an unsigned 32-bit 11662306a36Sopenharmony_ciword), which gives a max precision of 4.29s, more than enough for 11762306a36Sopenharmony_ciaudio applications... 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ciDue to the varied nature of timestamping needs, even for a single 12062306a36Sopenharmony_ciapplication, the audio_tstamp_config can be changed dynamically. In 12162306a36Sopenharmony_cithe ``STATUS`` ioctl, the parameters are read-only and do not allow for 12262306a36Sopenharmony_ciany application selection. To work around this limitation without 12362306a36Sopenharmony_ciimpacting legacy applications, a new ``STATUS_EXT`` ioctl is introduced 12462306a36Sopenharmony_ciwith read/write parameters. ALSA-lib will be modified to make use of 12562306a36Sopenharmony_ci``STATUS_EXT`` and effectively deprecate ``STATUS``. 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ciThe ALSA API only allows for a single audio timestamp to be reported 12862306a36Sopenharmony_ciat a time. This is a conscious design decision, reading the audio 12962306a36Sopenharmony_citimestamps from hardware registers or from IPC takes time, the more 13062306a36Sopenharmony_citimestamps are read the more imprecise the combined measurements 13162306a36Sopenharmony_ciare. To avoid any interpretation issues, a single (system, audio) 13262306a36Sopenharmony_citimestamp is reported. Applications that need different timestamps 13362306a36Sopenharmony_ciwill be required to issue multiple queries and perform an 13462306a36Sopenharmony_ciinterpolation of the results 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ciIn some hardware-specific configuration, the system timestamp is 13762306a36Sopenharmony_cilatched by a low-level audio subsystem, and the information provided 13862306a36Sopenharmony_ciback to the driver. Due to potential delays in the communication with 13962306a36Sopenharmony_cithe hardware, there is a risk of misalignment with the avail and delay 14062306a36Sopenharmony_ciinformation. To make sure applications are not confused, a 14162306a36Sopenharmony_cidriver_timestamp field is added in the snd_pcm_status structure; this 14262306a36Sopenharmony_citimestamp shows when the information is put together by the driver 14362306a36Sopenharmony_cibefore returning from the ``STATUS`` and ``STATUS_EXT`` ioctl. in most cases 14462306a36Sopenharmony_cithis driver_timestamp will be identical to the regular system tstamp. 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ciExamples of timestamping with HDAudio: 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci1. DMA timestamp, no compensation for DMA+analog delay 14962306a36Sopenharmony_ci:: 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci $ ./audio_time -p --ts_type=1 15262306a36Sopenharmony_ci playback: systime: 341121338 nsec, audio time 342000000 nsec, systime delta -878662 15362306a36Sopenharmony_ci playback: systime: 426236663 nsec, audio time 427187500 nsec, systime delta -950837 15462306a36Sopenharmony_ci playback: systime: 597080580 nsec, audio time 598000000 nsec, systime delta -919420 15562306a36Sopenharmony_ci playback: systime: 682059782 nsec, audio time 683020833 nsec, systime delta -961051 15662306a36Sopenharmony_ci playback: systime: 852896415 nsec, audio time 853854166 nsec, systime delta -957751 15762306a36Sopenharmony_ci playback: systime: 937903344 nsec, audio time 938854166 nsec, systime delta -950822 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci2. DMA timestamp, compensation for DMA+analog delay 16062306a36Sopenharmony_ci:: 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci $ ./audio_time -p --ts_type=1 -d 16362306a36Sopenharmony_ci playback: systime: 341053347 nsec, audio time 341062500 nsec, systime delta -9153 16462306a36Sopenharmony_ci playback: systime: 426072447 nsec, audio time 426062500 nsec, systime delta 9947 16562306a36Sopenharmony_ci playback: systime: 596899518 nsec, audio time 596895833 nsec, systime delta 3685 16662306a36Sopenharmony_ci playback: systime: 681915317 nsec, audio time 681916666 nsec, systime delta -1349 16762306a36Sopenharmony_ci playback: systime: 852741306 nsec, audio time 852750000 nsec, systime delta -8694 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci3. link timestamp, compensation for DMA+analog delay 17062306a36Sopenharmony_ci:: 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci $ ./audio_time -p --ts_type=2 -d 17362306a36Sopenharmony_ci playback: systime: 341060004 nsec, audio time 341062791 nsec, systime delta -2787 17462306a36Sopenharmony_ci playback: systime: 426242074 nsec, audio time 426244875 nsec, systime delta -2801 17562306a36Sopenharmony_ci playback: systime: 597080992 nsec, audio time 597084583 nsec, systime delta -3591 17662306a36Sopenharmony_ci playback: systime: 682084512 nsec, audio time 682088291 nsec, systime delta -3779 17762306a36Sopenharmony_ci playback: systime: 852936229 nsec, audio time 852940916 nsec, systime delta -4687 17862306a36Sopenharmony_ci playback: systime: 938107562 nsec, audio time 938112708 nsec, systime delta -5146 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ciExample 1 shows that the timestamp at the DMA level is close to 1ms 18162306a36Sopenharmony_ciahead of the actual playback time (as a side time this sort of 18262306a36Sopenharmony_cimeasurement can help define rewind safeguards). Compensating for the 18362306a36Sopenharmony_ciDMA-link delay in example 2 helps remove the hardware buffering but 18462306a36Sopenharmony_cithe information is still very jittery, with up to one sample of 18562306a36Sopenharmony_cierror. In example 3 where the timestamps are measured with the link 18662306a36Sopenharmony_ciwallclock, the timestamps show a monotonic behavior and a lower 18762306a36Sopenharmony_cidispersion. 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ciExample 3 and 4 are with USB audio class. Example 3 shows a high 19062306a36Sopenharmony_cioffset between audio time and system time due to buffering. Example 4 19162306a36Sopenharmony_cishows how compensating for the delay exposes a 1ms accuracy (due to 19262306a36Sopenharmony_cithe use of the frame counter by the driver) 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ciExample 3: DMA timestamp, no compensation for delay, delta of ~5ms 19562306a36Sopenharmony_ci:: 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci $ ./audio_time -p -Dhw:1 -t1 19862306a36Sopenharmony_ci playback: systime: 120174019 nsec, audio time 125000000 nsec, systime delta -4825981 19962306a36Sopenharmony_ci playback: systime: 245041136 nsec, audio time 250000000 nsec, systime delta -4958864 20062306a36Sopenharmony_ci playback: systime: 370106088 nsec, audio time 375000000 nsec, systime delta -4893912 20162306a36Sopenharmony_ci playback: systime: 495040065 nsec, audio time 500000000 nsec, systime delta -4959935 20262306a36Sopenharmony_ci playback: systime: 620038179 nsec, audio time 625000000 nsec, systime delta -4961821 20362306a36Sopenharmony_ci playback: systime: 745087741 nsec, audio time 750000000 nsec, systime delta -4912259 20462306a36Sopenharmony_ci playback: systime: 870037336 nsec, audio time 875000000 nsec, systime delta -4962664 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ciExample 4: DMA timestamp, compensation for delay, delay of ~1ms 20762306a36Sopenharmony_ci:: 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci $ ./audio_time -p -Dhw:1 -t1 -d 21062306a36Sopenharmony_ci playback: systime: 120190520 nsec, audio time 120000000 nsec, systime delta 190520 21162306a36Sopenharmony_ci playback: systime: 245036740 nsec, audio time 244000000 nsec, systime delta 1036740 21262306a36Sopenharmony_ci playback: systime: 370034081 nsec, audio time 369000000 nsec, systime delta 1034081 21362306a36Sopenharmony_ci playback: systime: 495159907 nsec, audio time 494000000 nsec, systime delta 1159907 21462306a36Sopenharmony_ci playback: systime: 620098824 nsec, audio time 619000000 nsec, systime delta 1098824 21562306a36Sopenharmony_ci playback: systime: 745031847 nsec, audio time 744000000 nsec, systime delta 1031847 216