@@ -102,6 +102,12 @@ static void app_stat(void* priv) {
102102
103103static void app_ptp_sync_notify (void * priv , struct mtl_ptp_sync_notify_meta * meta ) {
104104 struct st_app_context * ctx = priv ;
105+
106+ /* Store abs(delta) in circular buffer for moving average */
107+ ctx -> ptp_delta_history [ctx -> ptp_delta_history_idx ] = labs (meta -> delta );
108+ ctx -> ptp_delta_history_idx = (ctx -> ptp_delta_history_idx + 1 ) % PTP_DELTA_HISTORY_SIZE ;
109+ ctx -> ptp_sync_cnt ++ ;
110+
105111 if (!ctx -> ptp_systime_sync ) return ;
106112
107113 /* sync raw ptp to sys time */
@@ -112,9 +118,8 @@ static void app_ptp_sync_notify(void* priv, struct mtl_ptp_sync_notify_meta* met
112118 from_ts .tv_sec += meta -> master_utc_offset ; /* utc offset */
113119 uint64_t from_ns = st_timespec_to_ns (& from_ts );
114120
115- /* record the sync delta */
121+ /* record the sync delta for stats */
116122 int64_t delta = to_ns - from_ns ;
117- ctx -> ptp_sync_cnt ++ ;
118123 ctx -> ptp_sync_delta_sum += delta ;
119124 if (delta > ctx -> ptp_sync_delta_max ) ctx -> ptp_sync_delta_max = delta ;
120125 if (delta < ctx -> ptp_sync_delta_min ) ctx -> ptp_sync_delta_min = delta ;
@@ -436,7 +441,10 @@ int main(int argc, char** argv) {
436441 ctx -> para .nb_rx_hdr_split_queues = ctx -> rx_video_session_cnt ;
437442 }
438443
439- if (ctx -> ptp_systime_sync ) ctx -> para .ptp_sync_notify = app_ptp_sync_notify ;
444+ /* Register ptp_sync_notify for ptp_systime_sync or ptp_wait_stable */
445+ if (ctx -> ptp_systime_sync || ctx -> ptp_wait_stable_s > 0 ) {
446+ ctx -> para .ptp_sync_notify = app_ptp_sync_notify ;
447+ }
440448
441449 ctx -> st = mtl_init (& ctx -> para );
442450 if (!ctx -> st ) {
@@ -475,6 +483,93 @@ int main(int argc, char** argv) {
475483 }
476484 }
477485
486+ /* Wait for PTP to stabilize if requested */
487+ if (ctx -> ptp_wait_stable_s > 0 ) {
488+ int wait_s = ctx -> ptp_wait_stable_s ;
489+ int64_t threshold_ns = ctx -> ptp_wait_stable_threshold_ns ;
490+ if (threshold_ns <= 0 ) threshold_ns = 100 ; /* default 100ns threshold */
491+ bool stable = false;
492+
493+ info ("%s, waiting up to %d seconds for PTP delta to be below %" PRId64 " ns...\n" ,
494+ __func__ , wait_s , threshold_ns );
495+
496+ /* Start the device if not already started (needed for PTP to work) */
497+ if (!ctx -> runtime_session ) {
498+ ret = mtl_start (ctx -> st );
499+ if (ret < 0 ) {
500+ err ("%s, start dev fail for ptp wait %d\n" , __func__ , ret );
501+ st_app_ctx_free (ctx );
502+ return - EIO ;
503+ }
504+ }
505+
506+ /* Initialize delta tracking */
507+ for (int j = 0 ; j < PTP_DELTA_HISTORY_SIZE ; j ++ ) {
508+ ctx -> ptp_delta_history [j ] = INT64_MAX ;
509+ }
510+ ctx -> ptp_delta_history_idx = 0 ;
511+ ctx -> ptp_sync_cnt = 0 ;
512+
513+ for (int i = 0 ; i < wait_s * 10 && !stable ; i ++ ) {
514+ st_usleep (100 * 1000 ); /* 100ms sleep */
515+ if (ctx -> stop ) {
516+ err ("%s, aborted during PTP wait\n" , __func__ );
517+ st_app_ctx_free (ctx );
518+ return - EIO ;
519+ }
520+
521+ int sync_cnt = ctx -> ptp_sync_cnt ;
522+
523+ /* Check if we have enough samples for moving average */
524+ if (sync_cnt >= PTP_DELTA_HISTORY_SIZE ) {
525+ /* Compute moving average from circular buffer */
526+ int64_t sum = 0 ;
527+ for (int j = 0 ; j < PTP_DELTA_HISTORY_SIZE ; j ++ ) {
528+ sum += ctx -> ptp_delta_history [j ];
529+ }
530+ int64_t avg_delta = sum / PTP_DELTA_HISTORY_SIZE ;
531+
532+ if (avg_delta < threshold_ns ) {
533+ info ("%s, PTP stable after %d.%d seconds (moving avg delta: %" PRId64
534+ " ns, sync cnt: %d)\n" ,
535+ __func__ , i / 10 , (i % 10 ) * 100 , avg_delta , sync_cnt );
536+ stable = true;
537+ } else if ((i % 10 ) == 0 ) {
538+ info ("%s, PTP sync in progress, moving avg delta: %" PRId64
539+ " ns (threshold: %" PRId64 " ns, sync cnt: %d)\n" ,
540+ __func__ , avg_delta , threshold_ns , sync_cnt );
541+ }
542+ } else if ((i % 10 ) == 0 ) {
543+ info ("%s, waiting for PTP sync messages (cnt: %d, need: %d)...\n" , __func__ ,
544+ sync_cnt , PTP_DELTA_HISTORY_SIZE );
545+ }
546+ }
547+
548+ if (!stable ) {
549+ int64_t avg_delta = 0 ;
550+ if (ctx -> ptp_sync_cnt >= PTP_DELTA_HISTORY_SIZE ) {
551+ int64_t sum = 0 ;
552+ for (int j = 0 ; j < PTP_DELTA_HISTORY_SIZE ; j ++ ) {
553+ sum += ctx -> ptp_delta_history [j ];
554+ }
555+ avg_delta = sum / PTP_DELTA_HISTORY_SIZE ;
556+ }
557+ warn ("%s, PTP did not stabilize within %d seconds (moving avg delta: %" PRId64
558+ " ns), continuing anyway\n" ,
559+ __func__ , wait_s , avg_delta );
560+ }
561+
562+ /* Stop the device if we started it just for PTP wait (will be started later) */
563+ if (!ctx -> runtime_session ) {
564+ ret = mtl_stop (ctx -> st );
565+ if (ret < 0 ) {
566+ err ("%s, stop dev fail after ptp wait %d\n" , __func__ , ret );
567+ st_app_ctx_free (ctx );
568+ return - EIO ;
569+ }
570+ }
571+ }
572+
478573 if (ctx -> json_ctx -> user_time_offset ) {
479574 ctx -> user_time .user_time_offset = ctx -> json_ctx -> user_time_offset ;
480575 }
0 commit comments