blob: 388fe252f9d035fc793524dcb7a98a0471543cf0 [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
90int msync_session_get_start_policy(int fd, uint32_t *policy)
91{
92 int rc;
93 uint32_t kpolicy;
94
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
99 if (kpolicy == AMSYNC_START_V_FIRST)
100 *policy = AV_SYNC_START_V_FIRST;
101 else if (kpolicy == AMSYNC_START_A_FIRST)
102 *policy = AV_SYNC_START_A_FIRST;
103 else if (kpolicy == AMSYNC_START_ASAP)
104 *policy = AV_SYNC_START_ASAP;
105 else if (kpolicy == AMSYNC_START_ALIGN)
106 *policy = AV_SYNC_START_ALIGN;
107 else
108 *policy = AV_SYNC_START_NONE;
109 return rc;
110}
111int msync_session_set_start_policy(int fd, uint32_t policy)
112{
113 int rc;
114 uint32_t kpolicy;
115
116 if (policy == AV_SYNC_START_V_FIRST)
117 kpolicy = AMSYNC_START_V_FIRST;
118 else if (policy == AV_SYNC_START_A_FIRST)
119 kpolicy = AMSYNC_START_A_FIRST;
120 else if (policy == AV_SYNC_START_ASAP)
121 kpolicy = AMSYNC_START_ASAP;
122 else if (policy == AV_SYNC_START_ALIGN)
123 kpolicy = AMSYNC_START_ALIGN;
124 else
125 return -1;
126
127 rc = ioctl(fd, AMSYNCS_IOC_SET_START_POLICY, &kpolicy);
128 if (rc)
129 log_error("session[%d] set start policy errno:%d", fd, errno);
130 return rc;
131}
132
133static int msync_session_set_event(int fd, enum avs_event event, uint32_t value)
134{
135 struct session_event sevent;
136 int rc;
137
138 sevent.event = event;
139 sevent.value = value;
140
141 rc = ioctl(fd, AMSYNCS_IOC_SEND_EVENT, &sevent);
142 if (rc)
143 log_error("session[%d] send %d errno:%d", fd, event, errno);
144 return rc;
145}
146
147
148int msync_session_set_pause(int fd, bool pause)
149{
150 if (pause)
151 return msync_session_set_event(fd, AVS_PAUSE, 0);
152 else
153 return msync_session_set_event(fd, AVS_RESUME, 0);
154}
155
156int msync_session_get_wall(int fd, uint32_t *wall, uint32_t *interval)
157{
158 int rc;
159 struct pts_wall pwall;
160
161 rc = ioctl(fd, AMSYNCS_IOC_GET_WALL, &pwall);
162 if (rc)
163 log_error("session[%d] get wall errno:%d", fd, errno);
164
165 *wall = pwall.wall_clock;
166 if (interval)
167 *interval = pwall.interval;
168 return rc;
169}
170
171int msync_session_set_video_start(int fd, pts90K pts)
172{
173 return msync_session_set_event(fd, AVS_VIDEO_START, pts);
174}
175
176int msync_session_set_audio_start(int fd, pts90K pts, pts90K delay, uint32_t *mode)
177{
178 struct audio_start start;
179 int rc;
180
181 if (!mode)
182 return -EINVAL;
183
184 start.pts = pts;
185 start.delay = delay;
186 start.mode = 0;
187
188 rc = ioctl(fd, AMSYNCS_IOC_AUDIO_START, &start);
189 if (rc)
190 log_error("session[%d] audio start errno:%d", fd, errno);
191 else
192 *mode = start.mode;
193
194 return rc;
195}
196
197int msync_session_set_video_dis(int fd, pts90K pts)
198{
199 return msync_session_set_event(fd, AVS_VIDEO_TSTAMP_DISCONTINUITY, pts);
200}
201
202int msync_session_set_audio_dis(int fd, pts90K pts)
203{
204 return msync_session_set_event(fd, AVS_AUDIO_TSTAMP_DISCONTINUITY, pts);
205}
206
207int msync_session_set_rate(int fd, float speed)
208{
209 uint32_t krate = 1000*speed;
210 int rc;
211
212
213 rc = ioctl(fd, AMSYNCS_IOC_SET_RATE, &krate);
214 if (rc)
215 log_error("fd[%d] set rate errno:%d", fd, errno);
216 return rc;
217}
218
219int msync_session_get_rate(int fd, float *speed)
220{
221 uint32_t krate;
222 int rc;
223
224
225 rc = ioctl(fd, AMSYNCS_IOC_GET_RATE, &krate);
226 if (rc) {
227 log_error("fd[%d] get rate errno:%d", fd, errno);
228 return rc;
229 }
230 *speed = (float)krate/1000;
231 return 0;
232}
233
234int msync_session_set_name(int fd, const char* name)
235{
236 int rc;
237
238 rc = ioctl(fd, AMSYNCS_IOC_SET_NAME, name);
239 if (rc)
240 log_error("session[%d] set name errno:%d", fd, errno);
241 return rc;
242}
243
244int msync_session_update_vpts(int fd, uint32_t system, uint32_t pts, uint32_t delay)
245{
246 int rc;
247 struct pts_tri ts;
248
249 ts.wall_clock = system;
250 ts.pts = pts;
251 ts.delay = delay;
252
253 rc = ioctl(fd, AMSYNCS_IOC_SET_V_TS, &ts);
254 if (rc)
255 log_error("session[%d] set vts errno:%d", fd, errno);
256 return rc;
257}
258
259int msync_session_update_apts(int fd, uint32_t system, uint32_t pts, uint32_t delay)
260{
261 int rc;
262 struct pts_tri ts;
263
264 ts.wall_clock = system;
265 ts.pts = pts;
266 ts.delay = delay;
267
268 rc = ioctl(fd, AMSYNCS_IOC_SET_A_TS, &ts);
269 if (rc)
270 log_error("session[%d] set ats errno:%d", fd, errno);
271 return rc;
272}
273
274int msync_session_set_audio_stop(int fd)
275{
276 return msync_session_set_event(fd, AVS_AUDIO_STOP, 0);
277}
278
279int msync_session_set_video_stop(int fd)
280{
281 return msync_session_set_event(fd, AVS_VIDEO_STOP, 0);
282}
283
Song Zhaoe208d692021-04-19 15:38:52 -0700284int msync_session_get_stat (int fd, enum sync_mode *mode,
yongchun.li107a6162021-05-05 02:38:57 -0700285 bool *v_active, bool *a_active, bool *v_timeout,
286 bool *a_switch)
Song Zhaoea5a0412021-01-18 16:40:08 -0800287{
288 int rc;
289 struct session_sync_stat stat;
290
291 rc = ioctl(fd, AMSYNCS_IOC_GET_SYNC_STAT, &stat);
292 if (rc) {
293 log_error("fd[%d] get state errno:%d", fd, errno);
294 return rc;
295 }
296
297 switch (stat.mode) {
298 case AVS_MODE_A_MASTER:
299 *mode = AV_SYNC_MODE_AMASTER;
300 break;
301 case AVS_MODE_V_MASTER:
302 *mode = AV_SYNC_MODE_VMASTER;
303 break;
304 case AVS_MODE_PCR_MASTER:
305 *mode = AV_SYNC_MODE_PCR_MASTER;
306 break;
307 case AVS_MODE_IPTV:
308 *mode = AV_SYNC_MODE_IPTV;
309 break;
310 case AVS_MODE_FREE_RUN:
311 *mode = AV_SYNC_MODE_FREE_RUN;
312 break;
313 }
314 if (v_active)
315 *v_active = stat.v_active;
316 if (a_active)
317 *a_active = stat.a_active;
Song Zhaoe208d692021-04-19 15:38:52 -0700318 if (v_timeout)
319 *v_timeout = stat.v_timeout;
yongchun.li107a6162021-05-05 02:38:57 -0700320 if (a_switch)
321 *a_switch = stat.audio_switch;
Song Zhaoea5a0412021-01-18 16:40:08 -0800322 return rc;
323}
324
325bool msync_clock_started(int fd)
326{
327 uint32_t start = 0;
328 int rc;
329
330
331 rc = ioctl(fd, AMSYNCS_IOC_GET_CLOCK_START, &start);
332 if (rc)
333 log_error("session[%d] set clock start errno:%d", fd, errno);
334 return start != 0;
335}
336
Song Zhaod62bb392021-04-23 12:25:49 -0700337int msync_session_set_pcr(int fd, pts90K pts, uint64_t mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -0800338{
339 int rc;
Song Zhaod62bb392021-04-23 12:25:49 -0700340 struct pcr_pair pcr;
Song Zhaoea5a0412021-01-18 16:40:08 -0800341
Song Zhaod62bb392021-04-23 12:25:49 -0700342 pcr.pts = pts;
343 pcr.mono_clock = mono_clock;
Song Zhaoea5a0412021-01-18 16:40:08 -0800344 rc = ioctl(fd, AMSYNCS_IOC_SET_PCR, &pcr);
345 if (rc)
346 log_error("session[%d] set pcr %u errno:%d", fd, pcr, errno);
347
348 return rc;
349}
350
Song Zhaod62bb392021-04-23 12:25:49 -0700351int msync_session_get_pcr(int fd, pts90K *pts, uint64_t *mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -0800352{
353 int rc;
Song Zhaod62bb392021-04-23 12:25:49 -0700354 struct pcr_pair pcr;
Song Zhaoea5a0412021-01-18 16:40:08 -0800355
356 rc = ioctl(fd, AMSYNCS_IOC_GET_PCR, &pcr);
357 if (rc)
358 log_error("session[%d] set pcr %u errno:%d", fd, pcr, errno);
Song Zhaod62bb392021-04-23 12:25:49 -0700359 else {
360 *pts = pcr.pts;
361 *mono_clock = pcr.mono_clock;
362 }
363
364 return rc;
365}
366
367int msync_session_get_debug_mode(int fd, struct session_debug *debug)
368{
369 int rc;
370
371 rc = ioctl(fd, AMSYNCS_IOC_GET_DEBUG_MODE, debug);
372 if (rc)
373 log_error("session[%d] set debug mode errno:%d", fd, errno);
Song Zhaoea5a0412021-01-18 16:40:08 -0800374
375 return rc;
376}
yongchun.li107a6162021-05-05 02:38:57 -0700377
378int msync_session_set_audio_switch(int fd, bool start)
379{
380 log_info("audio switch set to %d", start);
381 return msync_session_set_event(fd, AVS_AUDIO_SWITCH, start);
Song Zhao8039f562021-05-18 18:11:25 -0700382}
383
384int msync_session_set_clock_dev(int fd, int32_t ppm)
385{
386 int rc;
387
388 rc = ioctl(fd, AMSYNCS_IOC_SET_CLK_DEV, &ppm);
389 if (rc)
390 log_error("session[%d] set clk dev errno:%d", fd, errno);
391 return rc;
392}
393
394int msync_session_get_clock_dev(int fd, int32_t *ppm)
395{
396 int rc;
397 int dev;
398
399 rc = ioctl(fd, AMSYNCS_IOC_GET_CLK_DEV, &dev);
400 if (rc)
401 log_error("session[%d] get clk dev errno:%d", fd, errno);
402 else
403 *ppm = dev;
404 return rc;
405}
Song Zhaof46932e2021-05-21 01:51:45 -0700406
407static int get_sysfs_uint32(const char *path, uint32_t *value)
408{
409 int fd;
410 char valstr[64];
411 uint32_t val = 0;
412
413 fd = open(path, O_RDONLY);
414 if (fd >= 0) {
415 memset(valstr, 0, 64);
416 read(fd, valstr, 64 - 1);
417 valstr[strlen(valstr)] = '\0';
418 close(fd);
419 } else {
420 log_error("unable to open file %s\n", path);
421 return -1;
422 }
423 if (sscanf(valstr, "%u", &val) < 1) {
424 log_error("unable to get pts from: %s", valstr);
425 return -1;
426 }
427 *value = val;
428 return 0;
429}
430
431int msync_session_get_disc_thres(int session_id, uint32_t *min, uint32_t *max)
432{
433 char name[64];
434
435 if (snprintf(name, sizeof(name),
436 "/sys/class/avsync_session%d/disc_thres_min", session_id) < 0)
437 return -1;
438 if (get_sysfs_uint32(name, min))
439 return -1;
440
441 if (snprintf(name, sizeof(name),
442 "/sys/class/avsync_session%d/disc_thres_max", session_id) < 0)
443 return -1;
444 if (get_sysfs_uint32(name, max))
445 return -1;
446
447 return 0;
448}