Re: Overflow in calculating audio timestamp

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 04. 02. 23 10:11, Alan Young wrote:

On 03/02/2023 18:02, Jaroslav Kysela wrote:
Thank you for your suggestion, but I think that the *whole* code for !get_time_info in update_audio_tstamp() should be recoded. The calling of ns_to_timespec64() is not enough to handle the boundary wraps in a decent range (tenths years for 24x7 operation)

Yes, indeed. My ambition was unnecessarily short.


and the bellow code is dangerous for 32-bit apps / system:

     if (crossed_boundary) {
                snd_BUG_ON(crossed_boundary != 1);
                runtime->hw_ptr_wrap += runtime->boundary;
     }

I don't understand why?
>
I would probably propose to have just hw_ptr_wrap +1 counter (we can reconstruct the frame position back by multiplication and do range check later),

Would that really help that much? It would extend the total possible duration but perhaps ~1523287 years(below) is sufficient.

remove snd_BUG_ON

Again, why?

For 32-bit apps the boundary is near to UINT32_MAX (see recalculate_boundary() function). So only one crossing point is not enough to cover a decent time range.

There should be a better check, if the add operation crosses the U64 range for snd_BUG_ON. In my eyes, it looks safer to use counter here and do the checks
in the function which uses this value.

and improve the timespec64 calculation.

The calculation should be split to two parts (tv_sec / tv_nsec):

1) calculate seconds: (frames / rate)
2) calculate the remainder (ns): ((frames % rate) * NSEC_PER_SEC) / rate

With 64-bit integer range, we should go up to (for 384000Hz rate):

2**64 / 384000 / 3600 / 24 / 365 = ~1523287 years


Yes indeed. How about this?

static inline void snd_pcm_lib_frames_to_timespec64(u64 frames, unsigned int rate, struct timespec64 *audio_tstamp)
{
	u32 remainder;
	audio_tstamp->tv_sec = div_u64_rem(frames, rate, &remainder);
	audio_tstamp->tv_nsec = div_u64(mul_u32_u32(remainder, NSEC_PER_SEC), rate);

Yes, this looks fine.

					Jaroslav

--
Jaroslav Kysela <perex@xxxxxxxx>
Linux Sound Maintainer; ALSA Project; Red Hat, Inc.




[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Pulse Audio]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux