blob: 428edaa41afa685b097b8332e046cab3ad612214 [file] [log] [blame]
Song Zhaoea5a0412021-01-18 16:40:08 -08001/*
2 * Copyright (c) 2020 Amlogic, Inc. All rights reserved.
3 *
4 * This source code is subject to the terms and conditions defined in the
5 * file 'LICENSE' which is part of this source code package.
6 *
7 * Description:
8 * User space AV sync module.
9 *
10 * Author: song.zhao@amlogic.com
11 */
12#include <errno.h>
13#include <fcntl.h>
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <sys/ioctl.h>
17#include <unistd.h>
18#include <linux/types.h>
Song Zhaof46932e2021-05-21 01:51:45 -070019#include <string.h>
Song Zhaoea5a0412021-01-18 16:40:08 -080020#include "msync.h"
21#include "aml_avsync_log.h"
22#include "msync_util.h"
23
24#define MSYNC_DEV "/dev/aml_msync"
25
26int msync_create_session()
27{
28 int fd;
29
30 fd = open(MSYNC_DEV, O_RDONLY | O_CLOEXEC);
31 if (fd < 0) {
32 log_error("%s errno:%d", MSYNC_DEV, errno);
33 return -1;
34 }
35 return fd;
36}
37
38void msync_destory_session(int fd)
39{
40 close(fd);
41}
42
43int msync_session_set_mode(int fd, enum sync_mode mode)
44{
45 int rc;
46 uint32_t kmode;
47
48 if (mode == AV_SYNC_MODE_VMASTER)
49 kmode = AVS_MODE_V_MASTER;
50 else if (mode == AV_SYNC_MODE_AMASTER)
51 kmode = AVS_MODE_A_MASTER;
52 else if (mode == AV_SYNC_MODE_PCR_MASTER)
53 kmode = AVS_MODE_PCR_MASTER;
54 else if (mode == AV_SYNC_MODE_IPTV)
55 kmode = AVS_MODE_IPTV;
56 else if (mode == AV_SYNC_MODE_FREE_RUN)
57 kmode = AVS_MODE_FREE_RUN;
58
59 rc = ioctl(fd, AMSYNCS_IOC_SET_MODE, &kmode);
60 if (rc)
61 log_error("session[%d] set mode errno:%d", fd, errno);
62 return rc;
63}
64
65int msync_session_get_mode(int fd, enum sync_mode *mode)
66{
67 int rc;
68 uint32_t kmode;
69
70 rc = ioctl(fd, AMSYNCS_IOC_GET_MODE, &kmode);
71 if (rc) {
72 log_error("session[%d] set mode errno:%d", fd, errno);
73 return rc;
74 }
75
76 if (kmode == AVS_MODE_V_MASTER)
77 *mode = AV_SYNC_MODE_VMASTER;
78 else if (kmode == AVS_MODE_A_MASTER)
79 *mode = AV_SYNC_MODE_AMASTER;
80 else if (kmode == AVS_MODE_PCR_MASTER)
81 *mode = AV_SYNC_MODE_PCR_MASTER;
82 else if (kmode == AVS_MODE_IPTV)
83 *mode = AV_SYNC_MODE_IPTV;
84 else if (kmode == AVS_MODE_FREE_RUN)
85 *mode = AV_SYNC_MODE_FREE_RUN;
86
87 return rc;
88}
89
bo.xiao5821fc72021-07-11 22:47:00 -040090int msync_session_get_start_policy(int fd, uint32_t *policy, int *timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -080091{
92 int rc;
bo.xiao5821fc72021-07-11 22:47:00 -040093 struct ker_start_policy kpolicy;
Song Zhaoea5a0412021-01-18 16:40:08 -080094
95 rc = ioctl(fd, AMSYNCS_IOC_GET_START_POLICY, &kpolicy);
96 if (rc)
97 log_error("session[%d] get start policy errno:%d", fd, errno);
98
bo.xiao5821fc72021-07-11 22:47:00 -040099 if (kpolicy.policy == AMSYNC_START_V_FIRST)
Song Zhaoea5a0412021-01-18 16:40:08 -0800100 *policy = AV_SYNC_START_V_FIRST;
bo.xiao5821fc72021-07-11 22:47:00 -0400101 else if (kpolicy.policy == AMSYNC_START_A_FIRST)
Song Zhaoea5a0412021-01-18 16:40:08 -0800102 *policy = AV_SYNC_START_A_FIRST;
bo.xiao5821fc72021-07-11 22:47:00 -0400103 else if (kpolicy.policy == AMSYNC_START_ASAP)
Song Zhaoea5a0412021-01-18 16:40:08 -0800104 *policy = AV_SYNC_START_ASAP;
bo.xiao5821fc72021-07-11 22:47:00 -0400105 else if (kpolicy.policy == AMSYNC_START_ALIGN)
Song Zhaoea5a0412021-01-18 16:40:08 -0800106 *policy = AV_SYNC_START_ALIGN;
107 else
108 *policy = AV_SYNC_START_NONE;
bo.xiao5821fc72021-07-11 22:47:00 -0400109
110 if (0 == rc)
111 *timeout = kpolicy.timeout;
112
Song Zhaoea5a0412021-01-18 16:40:08 -0800113 return rc;
114}
bo.xiao5821fc72021-07-11 22:47:00 -0400115int msync_session_set_start_policy(int fd, uint32_t policy, int timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -0800116{
117 int rc;
bo.xiao5821fc72021-07-11 22:47:00 -0400118 struct ker_start_policy kpolicy;
Song Zhaoea5a0412021-01-18 16:40:08 -0800119
120 if (policy == AV_SYNC_START_V_FIRST)
bo.xiao5821fc72021-07-11 22:47:00 -0400121 kpolicy.policy = AMSYNC_START_V_FIRST;
Song Zhaoea5a0412021-01-18 16:40:08 -0800122 else if (policy == AV_SYNC_START_A_FIRST)
bo.xiao5821fc72021-07-11 22:47:00 -0400123 kpolicy.policy = AMSYNC_START_A_FIRST;
Song Zhaoea5a0412021-01-18 16:40:08 -0800124 else if (policy == AV_SYNC_START_ASAP)
bo.xiao5821fc72021-07-11 22:47:00 -0400125 kpolicy.policy = AMSYNC_START_ASAP;
Song Zhaoea5a0412021-01-18 16:40:08 -0800126 else if (policy == AV_SYNC_START_ALIGN)
bo.xiao5821fc72021-07-11 22:47:00 -0400127 kpolicy.policy = AMSYNC_START_ALIGN;
Song Zhaoea5a0412021-01-18 16:40:08 -0800128 else
129 return -1;
130
bo.xiao5821fc72021-07-11 22:47:00 -0400131 kpolicy.timeout = timeout;
132
Song Zhaoea5a0412021-01-18 16:40:08 -0800133 rc = ioctl(fd, AMSYNCS_IOC_SET_START_POLICY, &kpolicy);
134 if (rc)
135 log_error("session[%d] set start policy errno:%d", fd, errno);
136 return rc;
137}
138
139static int msync_session_set_event(int fd, enum avs_event event, uint32_t value)
140{
141 struct session_event sevent;
142 int rc;
143
144 sevent.event = event;
145 sevent.value = value;
146
147 rc = ioctl(fd, AMSYNCS_IOC_SEND_EVENT, &sevent);
148 if (rc)
149 log_error("session[%d] send %d errno:%d", fd, event, errno);
150 return rc;
151}
152
153
154int msync_session_set_pause(int fd, bool pause)
155{
156 if (pause)
157 return msync_session_set_event(fd, AVS_PAUSE, 0);
158 else
159 return msync_session_set_event(fd, AVS_RESUME, 0);
160}
161
162int msync_session_get_wall(int fd, uint32_t *wall, uint32_t *interval)
163{
164 int rc;
165 struct pts_wall pwall;
166
167 rc = ioctl(fd, AMSYNCS_IOC_GET_WALL, &pwall);
168 if (rc)
169 log_error("session[%d] get wall errno:%d", fd, errno);
170
171 *wall = pwall.wall_clock;
172 if (interval)
173 *interval = pwall.interval;
174 return rc;
175}
176
177int msync_session_set_video_start(int fd, pts90K pts)
178{
179 return msync_session_set_event(fd, AVS_VIDEO_START, pts);
180}
181
182int msync_session_set_audio_start(int fd, pts90K pts, pts90K delay, uint32_t *mode)
183{
184 struct audio_start start;
185 int rc;
186
187 if (!mode)
188 return -EINVAL;
189
190 start.pts = pts;
191 start.delay = delay;
192 start.mode = 0;
193
194 rc = ioctl(fd, AMSYNCS_IOC_AUDIO_START, &start);
195 if (rc)
196 log_error("session[%d] audio start errno:%d", fd, errno);
197 else
198 *mode = start.mode;
199
200 return rc;
201}
202
203int msync_session_set_video_dis(int fd, pts90K pts)
204{
205 return msync_session_set_event(fd, AVS_VIDEO_TSTAMP_DISCONTINUITY, pts);
206}
207
208int msync_session_set_audio_dis(int fd, pts90K pts)
209{
210 return msync_session_set_event(fd, AVS_AUDIO_TSTAMP_DISCONTINUITY, pts);
211}
212
213int msync_session_set_rate(int fd, float speed)
214{
215 uint32_t krate = 1000*speed;
216 int rc;
217
218
219 rc = ioctl(fd, AMSYNCS_IOC_SET_RATE, &krate);
220 if (rc)
221 log_error("fd[%d] set rate errno:%d", fd, errno);
222 return rc;
223}
224
225int msync_session_get_rate(int fd, float *speed)
226{
227 uint32_t krate;
228 int rc;
229
230
231 rc = ioctl(fd, AMSYNCS_IOC_GET_RATE, &krate);
232 if (rc) {
233 log_error("fd[%d] get rate errno:%d", fd, errno);
234 return rc;
235 }
236 *speed = (float)krate/1000;
237 return 0;
238}
239
240int msync_session_set_name(int fd, const char* name)
241{
242 int rc;
243
244 rc = ioctl(fd, AMSYNCS_IOC_SET_NAME, name);
245 if (rc)
246 log_error("session[%d] set name errno:%d", fd, errno);
247 return rc;
248}
249
250int msync_session_update_vpts(int fd, uint32_t system, uint32_t pts, uint32_t delay)
251{
252 int rc;
253 struct pts_tri ts;
254
255 ts.wall_clock = system;
256 ts.pts = pts;
257 ts.delay = delay;
258
259 rc = ioctl(fd, AMSYNCS_IOC_SET_V_TS, &ts);
260 if (rc)
261 log_error("session[%d] set vts errno:%d", fd, errno);
262 return rc;
263}
264
265int msync_session_update_apts(int fd, uint32_t system, uint32_t pts, uint32_t delay)
266{
267 int rc;
268 struct pts_tri ts;
269
270 ts.wall_clock = system;
271 ts.pts = pts;
272 ts.delay = delay;
273
274 rc = ioctl(fd, AMSYNCS_IOC_SET_A_TS, &ts);
275 if (rc)
276 log_error("session[%d] set ats errno:%d", fd, errno);
277 return rc;
278}
279
280int msync_session_set_audio_stop(int fd)
281{
282 return msync_session_set_event(fd, AVS_AUDIO_STOP, 0);
283}
284
285int msync_session_set_video_stop(int fd)
286{
287 return msync_session_set_event(fd, AVS_VIDEO_STOP, 0);
288}
289
Song Zhaoe208d692021-04-19 15:38:52 -0700290int msync_session_get_stat (int fd, enum sync_mode *mode,
yongchun.li107a6162021-05-05 02:38:57 -0700291 bool *v_active, bool *a_active, bool *v_timeout,
292 bool *a_switch)
Song Zhaoea5a0412021-01-18 16:40:08 -0800293{
294 int rc;
295 struct session_sync_stat stat;
296
297 rc = ioctl(fd, AMSYNCS_IOC_GET_SYNC_STAT, &stat);
298 if (rc) {
299 log_error("fd[%d] get state errno:%d", fd, errno);
300 return rc;
301 }
302
303 switch (stat.mode) {
304 case AVS_MODE_A_MASTER:
305 *mode = AV_SYNC_MODE_AMASTER;
306 break;
307 case AVS_MODE_V_MASTER:
308 *mode = AV_SYNC_MODE_VMASTER;
309 break;
310 case AVS_MODE_PCR_MASTER:
311 *mode = AV_SYNC_MODE_PCR_MASTER;
312 break;
313 case AVS_MODE_IPTV:
314 *mode = AV_SYNC_MODE_IPTV;
315 break;
316 case AVS_MODE_FREE_RUN:
317 *mode = AV_SYNC_MODE_FREE_RUN;
318 break;
319 }
320 if (v_active)
321 *v_active = stat.v_active;
322 if (a_active)
323 *a_active = stat.a_active;
Song Zhaoe208d692021-04-19 15:38:52 -0700324 if (v_timeout)
325 *v_timeout = stat.v_timeout;
yongchun.li107a6162021-05-05 02:38:57 -0700326 if (a_switch)
327 *a_switch = stat.audio_switch;
Song Zhaoea5a0412021-01-18 16:40:08 -0800328 return rc;
329}
330
331bool msync_clock_started(int fd)
332{
333 uint32_t start = 0;
334 int rc;
335
336
337 rc = ioctl(fd, AMSYNCS_IOC_GET_CLOCK_START, &start);
338 if (rc)
339 log_error("session[%d] set clock start errno:%d", fd, errno);
340 return start != 0;
341}
342
Song Zhaod62bb392021-04-23 12:25:49 -0700343int msync_session_set_pcr(int fd, pts90K pts, uint64_t mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -0800344{
345 int rc;
Song Zhaod62bb392021-04-23 12:25:49 -0700346 struct pcr_pair pcr;
Song Zhaoea5a0412021-01-18 16:40:08 -0800347
Song Zhaod62bb392021-04-23 12:25:49 -0700348 pcr.pts = pts;
349 pcr.mono_clock = mono_clock;
Song Zhaoea5a0412021-01-18 16:40:08 -0800350 rc = ioctl(fd, AMSYNCS_IOC_SET_PCR, &pcr);
351 if (rc)
352 log_error("session[%d] set pcr %u errno:%d", fd, pcr, errno);
353
354 return rc;
355}
356
Song Zhaod62bb392021-04-23 12:25:49 -0700357int msync_session_get_pcr(int fd, pts90K *pts, uint64_t *mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -0800358{
359 int rc;
Song Zhaod62bb392021-04-23 12:25:49 -0700360 struct pcr_pair pcr;
Song Zhaoea5a0412021-01-18 16:40:08 -0800361
362 rc = ioctl(fd, AMSYNCS_IOC_GET_PCR, &pcr);
363 if (rc)
364 log_error("session[%d] set pcr %u errno:%d", fd, pcr, errno);
Song Zhaod62bb392021-04-23 12:25:49 -0700365 else {
366 *pts = pcr.pts;
367 *mono_clock = pcr.mono_clock;
368 }
369
370 return rc;
371}
372
373int msync_session_get_debug_mode(int fd, struct session_debug *debug)
374{
375 int rc;
376
377 rc = ioctl(fd, AMSYNCS_IOC_GET_DEBUG_MODE, debug);
378 if (rc)
379 log_error("session[%d] set debug mode errno:%d", fd, errno);
Song Zhaoea5a0412021-01-18 16:40:08 -0800380
381 return rc;
382}
yongchun.li107a6162021-05-05 02:38:57 -0700383
384int msync_session_set_audio_switch(int fd, bool start)
385{
386 log_info("audio switch set to %d", start);
387 return msync_session_set_event(fd, AVS_AUDIO_SWITCH, start);
Song Zhao8039f562021-05-18 18:11:25 -0700388}
389
390int msync_session_set_clock_dev(int fd, int32_t ppm)
391{
392 int rc;
393
394 rc = ioctl(fd, AMSYNCS_IOC_SET_CLK_DEV, &ppm);
395 if (rc)
396 log_error("session[%d] set clk dev errno:%d", fd, errno);
397 return rc;
398}
399
400int msync_session_get_clock_dev(int fd, int32_t *ppm)
401{
402 int rc;
403 int dev;
404
405 rc = ioctl(fd, AMSYNCS_IOC_GET_CLK_DEV, &dev);
406 if (rc)
407 log_error("session[%d] get clk dev errno:%d", fd, errno);
408 else
409 *ppm = dev;
410 return rc;
411}
Song Zhaof46932e2021-05-21 01:51:45 -0700412
413static int get_sysfs_uint32(const char *path, uint32_t *value)
414{
415 int fd;
416 char valstr[64];
417 uint32_t val = 0;
418
419 fd = open(path, O_RDONLY);
420 if (fd >= 0) {
421 memset(valstr, 0, 64);
422 read(fd, valstr, 64 - 1);
423 valstr[strlen(valstr)] = '\0';
424 close(fd);
425 } else {
426 log_error("unable to open file %s\n", path);
427 return -1;
428 }
429 if (sscanf(valstr, "%u", &val) < 1) {
430 log_error("unable to get pts from: %s", valstr);
431 return -1;
432 }
433 *value = val;
434 return 0;
435}
436
437int msync_session_get_disc_thres(int session_id, uint32_t *min, uint32_t *max)
438{
439 char name[64];
440
441 if (snprintf(name, sizeof(name),
442 "/sys/class/avsync_session%d/disc_thres_min", session_id) < 0)
443 return -1;
444 if (get_sysfs_uint32(name, min))
445 return -1;
446
447 if (snprintf(name, sizeof(name),
448 "/sys/class/avsync_session%d/disc_thres_max", session_id) < 0)
449 return -1;
450 if (get_sysfs_uint32(name, max))
451 return -1;
452
453 return 0;
454}