1 STATIC
void npv_clk_init_once(void)
5 r
= snd_pcm_status_malloc(&npv_clk_l
.ref
.status
);
7 npv_clk_fatal("alsa:unable to allocate an alsa status structure\n");
8 r
= snd_pcm_status_malloc(&npv_clk_l
.now
.status
);
10 npv_clk_fatal("alsa:unable to allocate an alsa status structure\n");
11 /* we pre-allocate alsa pcm hw_params container */
12 r
= snd_pcm_hw_params_malloc(&npv_clk_pcm_hw_params_l
);
14 npv_clk_fatal("alsa:unable to allocate hardware parameters context\n");
15 npv_clk_l
.paused
= false;
17 #define NO_REF_TIME_POINT 1
18 STATIC u8
npv_clk_get_audio_st_ts(s64
*ts
)
21 snd_pcm_audio_tstamp_config_t ac
;
31 unsigned int audio_rate_num_ui
;
33 unsigned int audio_rate_den_ui
;
38 if (!npv_clk_l
.ref_valid
)
39 return NO_REF_TIME_POINT
;
40 if (!npv_clk_l
.paused
) {
41 memset(npv_clk_l
.now
.status
, 0, snd_pcm_status_sizeof());
43 ac
.type_requested
= (unsigned int)npv_audio_selected_ts_type_p
;
44 snd_pcm_status_set_audio_htstamp_config(npv_clk_l
.now
.status
,
46 r
= snd_pcm_status(npv_audio_pcm_p
, npv_clk_l
.now
.status
);
48 npv_clk_fatal("alsa:unable to sample timing information for 'now' time point\n");
50 snd_pcm_status_get_audio_htstamp(npv_clk_l
.now
.status
, &hts
);
51 now_ns
= (f64
)hts
.tv_sec
* 1e9
+ (f64
)hts
.tv_nsec
;
53 snd_pcm_status_get_audio_htstamp(npv_clk_l
.ref
.status
, &hts
);
54 ref_status_ns
= (f64
)hts
.tv_sec
* 1e9
+ (f64
)hts
.tv_nsec
;
56 ref_audio_ts
= (f64
)npv_clk_l
.ref
.audio_st_ts
;
57 ref_delay_frs_n
= (f64
)snd_pcm_status_get_delay(npv_clk_l
.ref
.status
);
58 audio_tb_num
= (f64
)npv_audio_st_p
.tb
.num
;
59 audio_tb_den
= (f64
)npv_audio_st_p
.tb
.den
;
60 /*--------------------------------------------------------------------*/
61 r
= snd_pcm_hw_params_current(npv_audio_pcm_p
, npv_clk_pcm_hw_params_l
);
63 npv_clk_fatal("alsa:unable to get current hardware parameters\n");
64 r
= snd_pcm_hw_params_get_rate_numden(npv_clk_pcm_hw_params_l
,
65 &audio_rate_num_ui
, &audio_rate_den_ui
);
67 npv_clk_fatal("alsa:unable to get exact rate\n");
68 audio_rate_num
= (f64
)audio_rate_num_ui
;
69 audio_rate_den
= (f64
)audio_rate_den_ui
;
70 /*--------------------------------------------------------------------*/
71 written_frs_n
= (f64
)npv_clk_l
.ref
.written_ufrs_n
;
73 /* time translation */
74 ref_ns
= ref_status_ns
+ (ref_delay_frs_n
- written_frs_n
)
75 * audio_rate_den
* 1e9
/ audio_rate_num
;
76 /* basic linear interpolation */
77 now_audio_ts
= audio_tb_den
* 1e-9 * (now_ns
- ref_ns
) / audio_tb_num
79 *ts
= (s64
)lrint(now_audio_ts
);
82 #undef NO_REF_TIME_POINT
83 STATIC u8
npv_clk_get_video_st_ts(s64
*ts
)
94 audio_tb_num
= (f64
)npv_audio_st_p
.tb
.num
;
95 audio_tb_den
= (f64
)npv_audio_st_p
.tb
.den
;
96 video_tb_num
= (f64
)npv_video_st_p
.tb
.num
;
97 video_tb_den
= (f64
)npv_video_st_p
.tb
.den
;
99 r
= npv_clk_get_audio_st_ts(&now_audio_ts_s64
);
100 if (r
!= TS_RETURNED
)
102 now_audio_ts
= (f64
)now_audio_ts_s64
;
103 /* basic conversion */
104 now_video_ts
= audio_tb_num
* video_tb_den
* now_audio_ts
105 / (audio_tb_den
* video_tb_num
);
106 *ts
= (s64
)lrint(now_video_ts
);
109 STATIC
void npv_clk_ref_time_point_update(s64 audio_ts
,
110 snd_pcm_ufrs_t written_ufrs_n
)
113 snd_pcm_audio_tstamp_config_t ac
;
115 memset(npv_clk_l
.ref
.status
, 0, snd_pcm_status_sizeof());
117 ac
.type_requested
= (unsigned int)npv_audio_selected_ts_type_p
;
118 snd_pcm_status_set_audio_htstamp_config(npv_clk_l
.ref
.status
, &ac
);
119 r
= snd_pcm_status(npv_audio_pcm_p
, npv_clk_l
.ref
.status
);
121 npv_clk_fatal("unable to sample timing information for reference time point\n");
122 npv_clk_l
.ref
.audio_st_ts
= audio_ts
;
123 npv_clk_l
.ref
.written_ufrs_n
= written_ufrs_n
;
124 npv_clk_l
.ref_valid
= true;
126 STATIC
void npv_clk_invalidate(void)
128 npv_clk_l
.ref_valid
= false;
130 STATIC
void npv_clk_pause(void)
133 snd_pcm_audio_tstamp_config_t ac
;
135 npv_clk_l
.paused
= true;
136 memset(npv_clk_l
.now
.status
, 0, snd_pcm_status_sizeof());
138 ac
.type_requested
= (unsigned int)npv_audio_selected_ts_type_p
;
139 snd_pcm_status_set_audio_htstamp_config(npv_clk_l
.now
.status
, &ac
);
140 r
= snd_pcm_status(npv_audio_pcm_p
, npv_clk_l
.now
.status
);
142 npv_clk_fatal("alsa:unable to sample timing information for 'paused' time point\n");
144 STATIC
void npv_clk_unpause(void)
146 npv_clk_l
.paused
= false;
147 npv_clk_invalidate();