1 static void clk_init_once(void)
5 r
= snd_pcm_status_malloc(&clk_l
.ref
.status
);
7 FATALCLK("alsa:unable to allocate an alsa status structure\n");
8 r
= snd_pcm_status_malloc(&clk_l
.now
.status
);
10 FATALCLK("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(&clk_pcm_hw_params_l
);
14 FATALCLK("alsa:unable to allocate hardware parameters context\n");
16 #define NO_REF_TIME_POINT 1
17 static u8
clk_get_audio_st_ts(s64
*ts
)
20 snd_pcm_audio_tstamp_config_t ac
;
30 unsigned int audio_rate_num_ui
;
32 unsigned int audio_rate_den_ui
;
38 return NO_REF_TIME_POINT
;
39 memset(clk_l
.now
.status
, 0, snd_pcm_status_sizeof());
41 ac
.type_requested
= (unsigned int)audio_selected_ts_type_p
;
42 snd_pcm_status_set_audio_htstamp_config(clk_l
.now
.status
, &ac
);
43 r
= snd_pcm_status(audio_pcm_p
, clk_l
.now
.status
);
45 FATALCLK("alsa:unable to sample timing information for 'now' time point\n");
46 snd_pcm_status_get_audio_htstamp(clk_l
.now
.status
, &hts
);
47 now_ns
= (f64
)hts
.tv_sec
* 1e9
+ (f64
)hts
.tv_nsec
;
49 snd_pcm_status_get_audio_htstamp(clk_l
.ref
.status
, &hts
);
50 ref_status_ns
= (f64
)hts
.tv_sec
* 1e9
+ (f64
)hts
.tv_nsec
;
52 ref_audio_ts
= (f64
)clk_l
.ref
.audio_st_ts
;
53 ref_delay_frs_n
= (f64
)snd_pcm_status_get_delay(clk_l
.ref
.status
);
54 audio_tb_num
= (f64
)audio_st_p
.tb
.num
;
55 audio_tb_den
= (f64
)audio_st_p
.tb
.den
;
56 /*--------------------------------------------------------------------*/
57 r
= snd_pcm_hw_params_current(audio_pcm_p
, clk_pcm_hw_params_l
);
59 FATALCLK("alsa:unable to get current hardware parameters\n");
60 r
= snd_pcm_hw_params_get_rate_numden(clk_pcm_hw_params_l
,
61 &audio_rate_num_ui
, &audio_rate_den_ui
);
63 FATALCLK("alsa:unable to get exact rate\n");
64 audio_rate_num
= (f64
)audio_rate_num_ui
;
65 audio_rate_den
= (f64
)audio_rate_den_ui
;
66 /*--------------------------------------------------------------------*/
67 written_frs_n
= (f64
)clk_l
.ref
.written_ufrs_n
;
69 /* time translation */
70 ref_ns
= ref_status_ns
+ (ref_delay_frs_n
- written_frs_n
)
71 * audio_rate_den
* 1e9
/ audio_rate_num
;
72 /* basic linear interpolation */
73 now_audio_ts
= audio_tb_den
* 1e-9 * (now_ns
- ref_ns
) / audio_tb_num
75 *ts
= (s64
)lrint(now_audio_ts
);
78 #undef NO_REF_TIME_POINT
79 static u8
clk_get_video_st_ts(s64
*ts
)
90 audio_tb_num
= (f64
)audio_st_p
.tb
.num
;
91 audio_tb_den
= (f64
)audio_st_p
.tb
.den
;
92 video_tb_num
= (f64
)video_st_p
.tb
.num
;
93 video_tb_den
= (f64
)video_st_p
.tb
.den
;
95 r
= clk_get_audio_st_ts(&now_audio_ts_s64
);
98 now_audio_ts
= (f64
)now_audio_ts_s64
;
99 /* basic conversion */
100 now_video_ts
= audio_tb_num
* video_tb_den
* now_audio_ts
101 / (audio_tb_den
* video_tb_num
);
102 *ts
= (s64
)lrint(now_video_ts
);
105 static void clk_ref_time_point_update(s64 audio_ts
,
106 snd_pcm_ufrs_t written_ufrs_n
)
109 snd_pcm_audio_tstamp_config_t ac
;
111 memset(clk_l
.ref
.status
, 0, snd_pcm_status_sizeof());
113 ac
.type_requested
= (unsigned int)audio_selected_ts_type_p
;
114 snd_pcm_status_set_audio_htstamp_config(clk_l
.ref
.status
, &ac
);
115 r
= snd_pcm_status(audio_pcm_p
, clk_l
.ref
.status
);
117 FATALCLK("unable to sample timing information for reference time point\n");
118 clk_l
.ref
.audio_st_ts
= audio_ts
;
119 clk_l
.ref
.written_ufrs_n
= written_ufrs_n
;
120 clk_l
.ref_valid
= true;
122 static void clk_invalidate(void)
124 clk_l
.ref_valid
= false;