@@ -264,7 +264,7 @@ static int tx_audio_session_sync_pacing(struct mtl_main_impl* impl,
264264 struct st_tx_audio_session_impl * s , bool sync ,
265265 uint64_t required_tai ) {
266266 struct st_tx_audio_session_pacing * pacing = & s -> pacing ;
267- double pkt_time = pacing -> trs ;
267+ long double pkt_time = pacing -> trs ;
268268 /* always use MTL_PORT_P for ptp now */
269269 uint64_t ptp_time = mt_get_ptp_time (impl , MTL_PORT_P );
270270 uint64_t next_epochs = pacing -> cur_epochs + 1 ;
@@ -302,7 +302,18 @@ static int tx_audio_session_sync_pacing(struct mtl_main_impl* impl,
302302 }
303303 }
304304
305- to_epoch = tx_audio_pacing_time (pacing , epochs ) - ptp_time ;
305+ if (required_tai ) {
306+ to_epoch = (double )required_tai - ptp_time ;
307+ if (to_epoch > NS_PER_S ) {
308+ dbg ("%s(%d), required tai %" PRIu64 " ptp_epochs %" PRIu64 " epochs %" PRIu64 "\n" ,
309+ __func__ , s -> idx , required_tai , ptp_epochs , epochs );
310+ s -> stat_error_user_timestamp ++ ;
311+ to_epoch = NS_PER_S ; // do our best to slow down
312+ }
313+ } else {
314+ to_epoch = tx_audio_pacing_time (pacing , epochs ) - ptp_time ;
315+ }
316+
306317 if (to_epoch < 0 ) {
307318 /* time bigger than the assigned epoch time */
308319 s -> stat_epoch_mismatch ++ ;
@@ -313,13 +324,27 @@ static int tx_audio_session_sync_pacing(struct mtl_main_impl* impl,
313324 if (epochs < next_epochs ) s -> stat_epoch_onward += (next_epochs - epochs );
314325
315326 pacing -> cur_epochs = epochs ;
316- pacing -> cur_epoch_time = tx_audio_pacing_time (pacing , epochs );
317- pacing -> pacing_time_stamp = tx_audio_pacing_time_stamp (pacing , epochs );
318- pacing -> rtp_time_stamp = pacing -> pacing_time_stamp ;
327+
328+ if (required_tai ) {
329+ pacing -> cur_epoch_time = required_tai + pkt_time ; // prepare next packet
330+ /*
331+ * Cast [double] to intermediate [uint64_t] to extract 32 least significant bits.
332+ * If calculated time stored in [double] is larger than max uint32_t,
333+ * then result of direct cast to [uint32_t] results in max uint32_t which is not
334+ * what we want. "& 0xffffffff" is used to extract 32 least significant bits
335+ * without compiler trying to optimize-out intermediate cast.
336+ */
337+ pacing -> rtp_time_stamp =
338+ ((uint64_t )((required_tai / pkt_time ) * pacing -> pkt_time_sampling ) & 0xffffffff );
339+ } else {
340+ pacing -> cur_epoch_time = tx_audio_pacing_time (pacing , epochs );
341+ pacing -> rtp_time_stamp = tx_audio_pacing_time_stamp (pacing , epochs );
342+ }
343+
319344 if (s -> ops .rtp_timestamp_delta_us ) {
320345 double rtp_timestamp_delta_us = s -> ops .rtp_timestamp_delta_us ;
321346 int32_t rtp_timestamp_delta =
322- (rtp_timestamp_delta_us * NS_PER_US ) * pacing -> pkt_time_sampling / pacing -> trs ;
347+ (rtp_timestamp_delta_us * NS_PER_US ) * pacing -> pkt_time_sampling / pkt_time ;
323348 pacing -> rtp_time_stamp += rtp_timestamp_delta ;
324349 }
325350 pacing -> tsc_time_cursor = (double )mt_get_tsc (impl ) + to_epoch ;
0 commit comments