blob: afd5e9bbe2f275b2d877122bc48328b5c757878b [file] [log] [blame]
Song Zhaoc03ba122020-12-23 21:54:02 -08001/*
2 * Copyright (c) 2019 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 */
Song Zhaoea5a0412021-01-18 16:40:08 -08009#include <errno.h>
Song Zhaoc03ba122020-12-23 21:54:02 -080010#include <pthread.h>
11#include <stdbool.h>
12#include <stdlib.h>
13#include <stdio.h>
14#include <sys/time.h>
Song Zhaoea5a0412021-01-18 16:40:08 -080015#include <poll.h>
16#include <fcntl.h>
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <sys/prctl.h>
20#include <sys/ioctl.h>
Song Zhaoa2985cb2021-06-24 12:01:47 -070021#include <time.h>
Song Zhaoea5a0412021-01-18 16:40:08 -080022#include <unistd.h>
23//#include <linux/amlogic/msync.h>
Song Zhaoc03ba122020-12-23 21:54:02 -080024#include "aml_avsync.h"
25#include "queue.h"
26#include "pattern.h"
Song Zhaoc03ba122020-12-23 21:54:02 -080027#include "aml_avsync_log.h"
Song Zhaoea5a0412021-01-18 16:40:08 -080028#include "msync_util.h"
29#include "msync.h"
30#include <pthread.h>
wei.dubcc2ed22021-05-19 07:16:10 -040031#include "pcr_monitor.h"
Song Zhaoc03ba122020-12-23 21:54:02 -080032enum sync_state {
33 AV_SYNC_STAT_INIT = 0,
34 AV_SYNC_STAT_RUNNING = 1,
35 AV_SYNC_STAT_SYNC_SETUP = 2,
36 AV_SYNC_STAT_SYNC_LOST = 3,
37};
38
yongchun.li107a6162021-05-05 02:38:57 -070039enum audio_switch_state_ {
40 AUDIO_SWITCH_STAT_INIT = 0,
41 AUDIO_SWITCH_STAT_RESET = 1,
42 AUDIO_SWITCH_STAT_START = 2,
43 AUDIO_SWITCH_STAT_FINISH = 3,
44};
45
Song Zhaoea5a0412021-01-18 16:40:08 -080046#define SESSION_DEV "avsync_s"
47
Song Zhaoc03ba122020-12-23 21:54:02 -080048struct av_sync_session {
49 /* session id attached */
50 int session_id;
Song Zhaoea5a0412021-01-18 16:40:08 -080051 int fd;
52 bool attached;
53 enum sync_mode mode;
54 /* for audio trickplay */
55 enum sync_mode backup_mode;
56 enum sync_type type;
57 uint32_t start_policy;
Song Zhaoc03ba122020-12-23 21:54:02 -080058
Song Zhaoea5a0412021-01-18 16:40:08 -080059 /* playback time, will stop increasing during pause */
60 pts90K vpts;
61 pts90K apts;
62
63 /* phase adjustment of stream time for rate control (Video ONLY) */
Song Zhaoc03ba122020-12-23 21:54:02 -080064 pts90K phase;
65 bool phase_set;
66
67 /* pts of last rendered frame */
Song Zhaoea5a0412021-01-18 16:40:08 -080068 pts90K last_wall;
Song Zhaoc03ba122020-12-23 21:54:02 -080069 pts90K last_pts;
70 struct vframe *last_frame;
71
Song Zhaoe0bf6ad2021-07-09 11:28:42 -070072 /* pts of last pushed frame */
73 pts90K last_q_pts;
74
Song Zhaoc03ba122020-12-23 21:54:02 -080075 bool first_frame_toggled;
Song Zhaoc03ba122020-12-23 21:54:02 -080076 bool paused;
Song Zhaoea5a0412021-01-18 16:40:08 -080077 enum sync_state state;
Song Zhaoc03ba122020-12-23 21:54:02 -080078 void *pattern_detector;
79 void *frame_q;
Song Zhaoc03ba122020-12-23 21:54:02 -080080
Song Zhaoea5a0412021-01-18 16:40:08 -080081 /* start control */
82 int start_thres;
83 audio_start_cb audio_start;
84 void *audio_start_priv;
85
86 /* render property */
Song Zhaoc03ba122020-12-23 21:54:02 -080087 int delay;
88 pts90K vsync_interval;
89
90 /* state lock */
91 pthread_mutex_t lock;
92 /* pattern */
93 int last_holding_peroid;
Song Zhaoea5a0412021-01-18 16:40:08 -080094 bool session_started;
Song Zhaoc03ba122020-12-23 21:54:02 -080095
96 float speed;
97
Song Zhaoc03ba122020-12-23 21:54:02 -080098 /* pause pts */
99 pts90K pause_pts;
100 pause_pts_done pause_pts_cb;
101 void *pause_cb_priv;
Song Zhao5d2b4772021-01-18 16:40:08 -0800102
103 /* log control */
Song Zhaoa2985cb2021-06-24 12:01:47 -0700104 uint32_t last_log_syst;
Song Zhao5d2b4772021-01-18 16:40:08 -0800105 uint32_t sync_lost_cnt;
106 struct timeval sync_lost_print_time;
Song Zhaoea5a0412021-01-18 16:40:08 -0800107
108 pthread_t poll_thread;
109 /* pcr master, IPTV only */
110 bool quit_poll;
111 enum sync_mode active_mode;
Song Zhaof46932e2021-05-21 01:51:45 -0700112 uint32_t disc_thres_min;
113 uint32_t disc_thres_max;
Song Zhao35a82df2021-04-15 10:58:49 -0700114
115 /* error detection */
116 uint32_t last_poptime;
Song Zhaod62bb392021-04-23 12:25:49 -0700117 uint32_t outlier_cnt;
Song Zhao409739b2021-05-12 22:21:40 -0700118 pts90K last_disc_pts;
119
yongchun.li107a6162021-05-05 02:38:57 -0700120 // indicate set audio switch
121 bool in_audio_switch;
122 enum audio_switch_state_ audio_switch_state;
wei.dubcc2ed22021-05-19 07:16:10 -0400123
124 //pcr monitor handle
125 void *pcr_monitor;
126 int ppm;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700127
128 //video FPS detection
129 pts90K last_fpts;
130 int fps_interval;
131 int fps_interval_acc;
132 int fps_cnt;
133
134 //video freerun with rate control
135 uint32_t last_r_syst;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700136 bool debug_freerun;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700137
138 //Audio dropping detection
139 uint32_t audio_drop_cnt;
140 struct timeval audio_drop_start;
Song Zhaoc03ba122020-12-23 21:54:02 -0800141};
142
143#define MAX_FRAME_NUM 32
144#define DEFAULT_START_THRESHOLD 2
145#define TIME_UNIT90K (90000)
Song Zhaof46932e2021-05-21 01:51:45 -0700146#define AV_DISC_THRES_MIN (TIME_UNIT90K / 3)
147#define AV_DISC_THRES_MAX (TIME_UNIT90K * 10)
Song Zhao7daf3a12021-05-10 22:22:25 -0700148#define A_ADJ_THREDHOLD_HB (900 * 6) //60ms
149#define A_ADJ_THREDHOLD_LB (900 * 2) //20ms
Song Zhao52f55192021-05-06 10:52:21 -0700150#define AV_PATTERN_RESET_THRES (TIME_UNIT90K / 10)
Song Zhao5d2b4772021-01-18 16:40:08 -0800151#define SYNC_LOST_PRINT_THRESHOLD 10000000 //10 seconds In micro seconds
Song Zhaod62bb392021-04-23 12:25:49 -0700152#define LIVE_MODE(mode) ((mode) == AV_SYNC_MODE_PCR_MASTER || (mode) == AV_SYNC_MODE_IPTV)
153
Song Zhao065800e2021-05-26 15:56:06 -0700154#define STREAM_DISC_THRES (TIME_UNIT90K / 10)
Song Zhaod62bb392021-04-23 12:25:49 -0700155#define OUTLIER_MAX_CNT 8
Song Zhaoa2985cb2021-06-24 12:01:47 -0700156#define VALID_TS(x) ((x) != -1)
Song Zhaoc03ba122020-12-23 21:54:02 -0800157
158static uint64_t time_diff (struct timeval *b, struct timeval *a);
159static bool frame_expire(struct av_sync_session* avsync,
160 uint32_t systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800161 uint32_t interval,
Song Zhaoc03ba122020-12-23 21:54:02 -0800162 struct vframe * frame,
163 struct vframe * next_frame,
164 int toggle_cnt);
Song Zhao35a82df2021-04-15 10:58:49 -0700165static bool pattern_detect(struct av_sync_session* avsync,
Song Zhaoc03ba122020-12-23 21:54:02 -0800166 int cur_period,
167 int last_period);
Song Zhaoea5a0412021-01-18 16:40:08 -0800168static void * poll_thread(void * arg);
169static void trigger_audio_start_cb(struct av_sync_session *avsync,
170 avs_ascb_reason reason);
Song Zhaoc03ba122020-12-23 21:54:02 -0800171
Song Zhaoea5a0412021-01-18 16:40:08 -0800172int av_sync_open_session(int *session_id)
173{
174 int fd = msync_create_session();
175 int id, rc;
176
177 if (fd < 0) {
178 log_error("fail");
179 return -1;
180 }
181 rc = ioctl(fd, AMSYNC_IOC_ALLOC_SESSION, &id);
182 if (rc) {
183 log_error("new session errno:%d", errno);
184 return rc;
185 }
186 *session_id = id;
187 return fd;
188}
189
190void av_sync_close_session(int session)
191{
192 msync_destory_session(session);
193}
194
195static void* create_internal(int session_id,
Song Zhaoc03ba122020-12-23 21:54:02 -0800196 enum sync_mode mode,
Song Zhaoea5a0412021-01-18 16:40:08 -0800197 enum sync_type type,
Song Zhaoc03ba122020-12-23 21:54:02 -0800198 int start_thres,
Song Zhaoea5a0412021-01-18 16:40:08 -0800199 bool attach)
Song Zhaoc03ba122020-12-23 21:54:02 -0800200{
201 struct av_sync_session *avsync = NULL;
Song Zhaoea5a0412021-01-18 16:40:08 -0800202 char dev_name[20];
Song Zhaoc03ba122020-12-23 21:54:02 -0800203
204 avsync = (struct av_sync_session *)calloc(1, sizeof(*avsync));
205 if (!avsync) {
206 log_error("OOM");
207 return NULL;
208 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800209
210 if (type == AV_SYNC_TYPE_VIDEO) {
211 avsync->pattern_detector = create_pattern_detector();
212 if (!avsync->pattern_detector) {
213 log_error("pd create fail");
214 goto err;
215 }
216
217 if (!start_thres)
218 avsync->start_thres = DEFAULT_START_THRESHOLD;
219 else {
220 if (start_thres > 5) {
221 log_error("start_thres too big: %d", start_thres);
222 goto err2;
223 }
224 avsync->start_thres = start_thres;
225 }
226 avsync->phase_set = false;
227 avsync->first_frame_toggled = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800228 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800229
230 avsync->type = type;
Song Zhaoc03ba122020-12-23 21:54:02 -0800231 avsync->state = AV_SYNC_STAT_INIT;
Song Zhaoc03ba122020-12-23 21:54:02 -0800232 avsync->paused = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800233 avsync->session_id = session_id;
Song Zhaoea5a0412021-01-18 16:40:08 -0800234 avsync->backup_mode = mode;
Song Zhaoc03ba122020-12-23 21:54:02 -0800235 avsync->last_frame = NULL;
Song Zhaoea5a0412021-01-18 16:40:08 -0800236 avsync->session_started = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800237 avsync->speed = 1.0f;
238 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
Song Zhao409739b2021-05-12 22:21:40 -0700239 avsync->vsync_interval = -1;
240 avsync->last_disc_pts = -1;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700241 avsync->last_log_syst = -1;
242 avsync->last_pts = -1;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700243 avsync->last_q_pts = -1;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700244 avsync->last_wall = -1;
245 avsync->fps_interval = -1;
246 avsync->last_r_syst = -1;
Song Zhaof46932e2021-05-21 01:51:45 -0700247 if (msync_session_get_disc_thres(session_id,
248 &avsync->disc_thres_min, &avsync->disc_thres_max)) {
249 log_error("fail to get disc thres", dev_name, errno);
250 avsync->disc_thres_min = AV_DISC_THRES_MIN;
251 avsync->disc_thres_max = AV_DISC_THRES_MAX;
252 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800253
254 pthread_mutex_init(&avsync->lock, NULL);
Song Zhaof46932e2021-05-21 01:51:45 -0700255 log_info("[%d] mode %d type %d start_thres %d disc_thres %u/%u",
256 session_id, mode, type, start_thres,
257 avsync->disc_thres_min, avsync->disc_thres_max);
Song Zhaoea5a0412021-01-18 16:40:08 -0800258
259 snprintf(dev_name, sizeof(dev_name), "/dev/%s%d", SESSION_DEV, session_id);
260 avsync->fd = open(dev_name, O_RDONLY | O_CLOEXEC);
261 if (avsync->fd < 0) {
262 log_error("open %s errno %d", dev_name, errno);
263 goto err2;
264 }
265
wei.dubcc2ed22021-05-19 07:16:10 -0400266 if (avsync->type == AV_SYNC_TYPE_PCR) {
267 if (pcr_monitor_init(&avsync->pcr_monitor)) {
268 log_error("pcr monitor init");
269 goto err2;
270 }
271 }
272
Song Zhaoea5a0412021-01-18 16:40:08 -0800273 if (!attach) {
274 msync_session_set_mode(avsync->fd, mode);
275 avsync->mode = mode;
276 } else {
277 avsync->attached = true;
278 if (msync_session_get_mode(avsync->fd, &avsync->mode)) {
279 log_error("get mode");
wei.dubcc2ed22021-05-19 07:16:10 -0400280 goto err3;
Song Zhaoea5a0412021-01-18 16:40:08 -0800281 }
282 avsync->backup_mode = avsync->mode;
283 if (msync_session_get_start_policy(avsync->fd, &avsync->start_policy)) {
284 log_error("get policy");
wei.dubcc2ed22021-05-19 07:16:10 -0400285 goto err3;
Song Zhaoea5a0412021-01-18 16:40:08 -0800286 }
yongchun.li107a6162021-05-05 02:38:57 -0700287 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700288 NULL, NULL, NULL, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -0700289 log_error("get state");
wei.dubcc2ed22021-05-19 07:16:10 -0400290 goto err3;
yongchun.li107a6162021-05-05 02:38:57 -0700291 }
292 if (avsync->in_audio_switch) {
293 log_info("audio_switch_state reseted the audio");
294 avsync->audio_switch_state = AUDIO_SWITCH_STAT_RESET;
295 }
296
Song Zhaoea5a0412021-01-18 16:40:08 -0800297 log_info("[%d]retrieve sync mode %d policy %d",
298 session_id, avsync->mode, avsync->start_policy);
299 }
300
Song Zhaoc03ba122020-12-23 21:54:02 -0800301 return avsync;
wei.dubcc2ed22021-05-19 07:16:10 -0400302err3:
303 if (avsync->pcr_monitor)
304 pcr_monitor_destroy(avsync->pcr_monitor);
Song Zhaoea5a0412021-01-18 16:40:08 -0800305err2:
306 destroy_pattern_detector(avsync->pattern_detector);
307err:
308 free(avsync);
309 return NULL;
310}
311
312void* av_sync_create(int session_id,
313 enum sync_mode mode,
314 enum sync_type type,
315 int start_thres)
316{
317 return create_internal(session_id, mode,
318 type, start_thres, false);
319}
320
321void* av_sync_attach(int session_id, enum sync_type type)
322{
323 return create_internal(session_id, AV_SYNC_MODE_MAX,
324 type, 0, true);
325}
326
327int av_sync_video_config(void *sync, struct video_config* config)
328{
329 struct av_sync_session *avsync = (struct av_sync_session *)sync;
330
331 if (!avsync || !config)
332 return -1;
333
334 if (config->delay != 1 && config->delay != 2) {
335 log_error("invalid delay: %d\n", config->delay);
336 return -1;
337 }
338
339 avsync->delay = config->delay;
340
341 log_info("[%d] delay: %d",
342 avsync->session_id, config->delay);
343 return 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800344}
345
346static int internal_stop(struct av_sync_session *avsync)
347{
348 int ret = 0;
349 struct vframe *frame;
350
351 pthread_mutex_lock(&avsync->lock);
Song Zhaoc03ba122020-12-23 21:54:02 -0800352 while (!dqueue_item(avsync->frame_q, (void **)&frame)) {
353 frame->free(frame);
354 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800355 avsync->state = AV_SYNC_STAT_INIT;
Song Zhaoc03ba122020-12-23 21:54:02 -0800356 pthread_mutex_unlock(&avsync->lock);
357 return ret;
358}
359
360/* destroy and detach from kernel session */
361void av_sync_destroy(void *sync)
362{
363 struct av_sync_session *avsync = (struct av_sync_session *)sync;
364
365 if (!avsync)
366 return;
367
Song Zhaoea5a0412021-01-18 16:40:08 -0800368 log_info("[%d]begin", avsync->session_id);
369 if (avsync->state != AV_SYNC_STAT_INIT) {
370 if (avsync->type == AV_SYNC_TYPE_VIDEO)
371 internal_stop(avsync);
Song Zhaoc03ba122020-12-23 21:54:02 -0800372
Song Zhaoea5a0412021-01-18 16:40:08 -0800373 avsync->quit_poll = true;
374 if (avsync->poll_thread) {
375 pthread_join(avsync->poll_thread, NULL);
376 avsync->poll_thread = 0;
377 }
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700378 if (avsync->type == AV_SYNC_TYPE_AUDIO)
379 trigger_audio_start_cb(avsync, AV_SYNC_ASCB_STOP);
Song Zhaoaf368d52021-02-17 17:53:45 -0800380 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800381
Song Zhaoea5a0412021-01-18 16:40:08 -0800382 if (avsync->session_started) {
383 if (avsync->type == AV_SYNC_TYPE_VIDEO)
384 msync_session_set_video_stop(avsync->fd);
385 else
386 msync_session_set_audio_stop(avsync->fd);
387 }
wei.dubcc2ed22021-05-19 07:16:10 -0400388
389 if(avsync->pcr_monitor)
390 pcr_monitor_destroy(avsync->pcr_monitor);
391
Song Zhaoea5a0412021-01-18 16:40:08 -0800392 close(avsync->fd);
Song Zhaoc03ba122020-12-23 21:54:02 -0800393 pthread_mutex_destroy(&avsync->lock);
Song Zhaoea5a0412021-01-18 16:40:08 -0800394 if (avsync->type == AV_SYNC_TYPE_VIDEO) {
395 destroy_q(avsync->frame_q);
396 destroy_pattern_detector(avsync->pattern_detector);
397 }
398 log_info("[%d]done", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800399 free(avsync);
Song Zhaoea5a0412021-01-18 16:40:08 -0800400}
401
402int avs_sync_set_start_policy(void *sync, enum sync_start_policy policy)
403{
404 struct av_sync_session *avsync = (struct av_sync_session *)sync;
405
406 if (!avsync || !avsync->fd)
407 return -1;
408
409 log_info("[%d]policy %u --> %u", avsync->start_policy, policy);
410 avsync->start_policy = policy;
411 /* v_peek will be handled by libamlavsync */
412 if (policy != AV_SYNC_START_NONE &&
413 policy != AV_SYNC_START_V_PEEK)
414 return msync_session_set_start_policy(avsync->fd, policy);
415
416 return 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800417}
418
419int av_sync_pause(void *sync, bool pause)
420{
421 struct av_sync_session *avsync = (struct av_sync_session *)sync;
yongchun.li107a6162021-05-05 02:38:57 -0700422 bool v_active, a_active, v_timeout;
Song Zhaoea5a0412021-01-18 16:40:08 -0800423 int rc;
Song Zhaoc03ba122020-12-23 21:54:02 -0800424
425 if (!avsync)
426 return -1;
427
Song Zhaoea5a0412021-01-18 16:40:08 -0800428 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER)
429 return -1;
Song Zhaoc03ba122020-12-23 21:54:02 -0800430
yongchun.li107a6162021-05-05 02:38:57 -0700431 rc = msync_session_get_stat(avsync->fd, &avsync->active_mode,
432 &v_active, &a_active, &v_timeout,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700433 &avsync->in_audio_switch, SRC_A);
yongchun.li107a6162021-05-05 02:38:57 -0700434
yongchun.li5f52fb02021-06-04 18:13:05 -0700435 /* ignore only when video try to pause when audio is acive, on which
436 the control of the STC will be relays.
437 When resume,it can do always as it is possible that video just
438 paused earlier without audio yet,then audio added later before resume.
439 We shall not igore that otherwise it could cause video freeze. */
440 if (avsync->mode == AV_SYNC_MODE_AMASTER &&
441 avsync->type == AV_SYNC_TYPE_VIDEO &&
442 a_active &&
443 !avsync->in_audio_switch) {
444 if (!pause) {
445 log_info("[%d] clear video pause when audio active",
446 avsync->session_id);
447 avsync->paused = pause;
448 } else {
449 log_info("[%d] ignore the pause from video when audio active",
450 avsync->session_id);
451 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800452 return 0;
yongchun.li5f52fb02021-06-04 18:13:05 -0700453 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800454
yongchun.li107a6162021-05-05 02:38:57 -0700455 if (avsync->in_audio_switch && avsync->type == AV_SYNC_TYPE_AUDIO) {
456 log_info("[%d] ignore the pause from audio", avsync->session_id);
457 avsync->audio_switch_state = AUDIO_SWITCH_STAT_RESET;
458 return 0;
459 }
460
Song Zhaoea5a0412021-01-18 16:40:08 -0800461 rc = msync_session_set_pause(avsync->fd, pause);
Song Zhaoc03ba122020-12-23 21:54:02 -0800462 avsync->paused = pause;
Song Zhaoea5a0412021-01-18 16:40:08 -0800463 log_info("[%d]paused:%d type:%d rc %d",
464 avsync->session_id, pause, avsync->type, rc);
Song Zhaoc03ba122020-12-23 21:54:02 -0800465
Song Zhaoea5a0412021-01-18 16:40:08 -0800466 return rc;
Song Zhaoc03ba122020-12-23 21:54:02 -0800467}
468
469int av_sync_push_frame(void *sync , struct vframe *frame)
470{
471 int ret;
472 struct vframe *prev;
473 struct av_sync_session *avsync = (struct av_sync_session *)sync;
474
475 if (!avsync)
476 return -1;
477
Song Zhaoea5a0412021-01-18 16:40:08 -0800478 if (!avsync->frame_q) {
479 /* policy should be final now */
480 if (msync_session_get_start_policy(avsync->fd, &avsync->start_policy)) {
481 log_error("[%d]get policy", avsync->session_id);
482 return -1;
483 }
484
485 avsync->frame_q = create_q(MAX_FRAME_NUM);
486 if (!avsync->frame_q) {
487 log_error("[%d]create queue fail", avsync->session_id);
488 return -1;
489 }
490
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700491 /* for debugging */
492 {
Song Zhaoea5a0412021-01-18 16:40:08 -0800493 int ret;
494
495 ret = pthread_create(&avsync->poll_thread, NULL, poll_thread, avsync);
496 if (ret) {
497 log_error("[%d]create poll thread errno %d", avsync->session_id, errno);
498 destroy_q(avsync->frame_q);
499 return -1;
500 }
501 }
502 }
503
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700504 if (avsync->last_q_pts != -1) {
505 if (avsync->last_q_pts == frame->pts && avsync->mode == AV_SYNC_MODE_AMASTER) {
506 /* TODO: wrong, should remove from back of queue */
Song Zhaoc03ba122020-12-23 21:54:02 -0800507 dqueue_item(avsync->frame_q, (void **)&prev);
508 prev->free(prev);
Song Zhaoea5a0412021-01-18 16:40:08 -0800509 log_info ("[%d]drop frame with same pts %u", avsync->session_id, frame->pts);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700510 } else if (avsync->fps_cnt < 100) {
511 int32_t interval = frame->pts - avsync->last_q_pts;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700512
513 if (interval > 0 && interval <= 4500) {
514 if (avsync->fps_interval_acc == -1) {
515 avsync->fps_interval_acc = interval;
516 avsync->fps_cnt = 1;
517 } else {
518 avsync->fps_interval_acc += interval;
519 avsync->fps_cnt++;
520 avsync->fps_interval = avsync->fps_interval_acc / avsync->fps_cnt;
521 if (avsync->fps_cnt == 100)
522 log_info("[%d] fps_interval = %d", avsync->session_id, avsync->fps_interval);
523 }
524 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800525 }
526 }
527
Song Zhao065800e2021-05-26 15:56:06 -0700528 if (frame->duration == -1)
529 frame->duration = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800530 frame->hold_period = 0;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700531 avsync->last_q_pts = frame->pts;
Song Zhaoc03ba122020-12-23 21:54:02 -0800532 ret = queue_item(avsync->frame_q, frame);
533 if (avsync->state == AV_SYNC_STAT_INIT &&
534 queue_size(avsync->frame_q) >= avsync->start_thres) {
535 avsync->state = AV_SYNC_STAT_RUNNING;
Song Zhaoea5a0412021-01-18 16:40:08 -0800536 log_info("[%d]state: init --> running", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800537 }
538
539 if (ret)
540 log_error("%s queue fail:%d", ret);
Song Zhaoea5a0412021-01-18 16:40:08 -0800541 log_debug("[%d]push %u", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800542 return ret;
543
544}
545
546struct vframe *av_sync_pop_frame(void *sync)
547{
Song Zhaoea5a0412021-01-18 16:40:08 -0800548 struct vframe *frame = NULL, *enter_last_frame = NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800549 struct av_sync_session *avsync = (struct av_sync_session *)sync;
550 int toggle_cnt = 0;
551 uint32_t systime;
Song Zhao468fd652021-01-15 22:13:04 -0800552 bool pause_pts_reached = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800553 uint32_t interval;
Song Zhaoc03ba122020-12-23 21:54:02 -0800554
555 pthread_mutex_lock(&avsync->lock);
556 if (avsync->state == AV_SYNC_STAT_INIT) {
Song Zhaod62bb392021-04-23 12:25:49 -0700557 log_info("[%d]in state INIT", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800558 goto exit;
559 }
560
Song Zhaoea5a0412021-01-18 16:40:08 -0800561 if (!avsync->session_started) {
Song Zhao35a82df2021-04-15 10:58:49 -0700562 uint32_t pts;
563
Song Zhaoc03ba122020-12-23 21:54:02 -0800564 if (peek_item(avsync->frame_q, (void **)&frame, 0) || !frame) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800565 log_info("[%d]empty q", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800566 goto exit;
567 }
Song Zhao35a82df2021-04-15 10:58:49 -0700568 msync_session_get_wall(avsync->fd, &systime, &interval);
569 pts = frame->pts - avsync->delay * interval;
570 msync_session_set_video_start(avsync->fd, pts);
Song Zhaoea5a0412021-01-18 16:40:08 -0800571 avsync->session_started = true;
Song Zhao35a82df2021-04-15 10:58:49 -0700572 log_info("[%d]video start %u", avsync->session_id, pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800573 }
574
Song Zhaoea5a0412021-01-18 16:40:08 -0800575 if (avsync->start_policy == AV_SYNC_START_ALIGN &&
Song Zhaod4109b62021-04-30 08:47:17 -0700576 !avsync->first_frame_toggled &&
577 !msync_clock_started(avsync->fd)) {
578 pthread_mutex_unlock(&avsync->lock);
Song Zhaoea5a0412021-01-18 16:40:08 -0800579 log_trace("[%d]clock not started", avsync->session_id);
580 return NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800581 }
582
Song Zhaoea5a0412021-01-18 16:40:08 -0800583 enter_last_frame = avsync->last_frame;
584 msync_session_get_wall(avsync->fd, &systime, &interval);
585
586 /* handle refresh rate change */
587 if (avsync->vsync_interval == AV_SYNC_INVALID_PAUSE_PTS ||
588 avsync->vsync_interval != interval) {
589 log_info("[%d]vsync interval update %d --> %u",
590 avsync->session_id, avsync->vsync_interval, interval);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700591 if (avsync->fps_interval == -1)
592 avsync->fps_interval = interval;
Song Zhaoea5a0412021-01-18 16:40:08 -0800593 avsync->vsync_interval = interval;
594 avsync->phase_set = false;
595 reset_pattern(avsync->pattern_detector);
596 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800597 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
598 struct vframe *next_frame = NULL;
599
600 peek_item(avsync->frame_q, (void **)&next_frame, 1);
601 if (next_frame)
Song Zhaof46932e2021-05-21 01:51:45 -0700602 log_debug("[%d]cur_f %u next_f %u size %d",
603 avsync->session_id, frame->pts, next_frame->pts, queue_size(avsync->frame_q));
Song Zhaoea5a0412021-01-18 16:40:08 -0800604 if (frame_expire(avsync, systime, interval,
605 frame, next_frame, toggle_cnt)) {
606 log_debug("[%d]cur_f %u expire", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800607 toggle_cnt++;
608
Song Zhao35a82df2021-04-15 10:58:49 -0700609 if (pattern_detect(avsync,
Song Zhaoc03ba122020-12-23 21:54:02 -0800610 (avsync->last_frame?avsync->last_frame->hold_period:0),
Song Zhao35a82df2021-04-15 10:58:49 -0700611 avsync->last_holding_peroid))
612 log_info("[%d] %u break the pattern", avsync->session_id, avsync->last_frame->pts);
613
Song Zhaoc03ba122020-12-23 21:54:02 -0800614 if (avsync->last_frame)
615 avsync->last_holding_peroid = avsync->last_frame->hold_period;
616
617 dqueue_item(avsync->frame_q, (void **)&frame);
618 if (avsync->last_frame) {
619 /* free frame that are not for display */
Song Zhaoea5a0412021-01-18 16:40:08 -0800620 if (toggle_cnt > 1) {
Song Zhao35a82df2021-04-15 10:58:49 -0700621 log_debug("[%d]free %u cur %u system/d %u/%u", avsync->session_id,
622 avsync->last_frame->pts, frame->pts, systime, systime - avsync->last_poptime);
Song Zhaoc03ba122020-12-23 21:54:02 -0800623 avsync->last_frame->free(avsync->last_frame);
Song Zhaoea5a0412021-01-18 16:40:08 -0800624 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800625 } else {
626 avsync->first_frame_toggled = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800627 log_info("[%d]first frame %u", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800628 }
629 avsync->last_frame = frame;
Song Zhao5d2b4772021-01-18 16:40:08 -0800630 avsync->last_pts = frame->pts;
Song Zhaoc03ba122020-12-23 21:54:02 -0800631 } else
632 break;
633 }
634
635 /* pause pts */
636 if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS && avsync->last_frame) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800637 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
Song Zhao468fd652021-01-15 22:13:04 -0800638 pause_pts_reached = true;
Song Zhaoc03ba122020-12-23 21:54:02 -0800639 else
Song Zhao468fd652021-01-15 22:13:04 -0800640 pause_pts_reached = (int)(avsync->last_frame->pts - avsync->pause_pts) >= 0;
641 } else if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS) {
642 if (!peek_item(avsync->frame_q, (void **)&frame, 0))
643 pause_pts_reached = (int)(frame->pts - avsync->pause_pts) >= 0;
644 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800645
Song Zhao468fd652021-01-15 22:13:04 -0800646 if (pause_pts_reached) {
647 if (avsync->pause_pts_cb)
648 avsync->pause_pts_cb(avsync->pause_pts,
Song Zhaoc03ba122020-12-23 21:54:02 -0800649 avsync->pause_cb_priv);
650
Song Zhao468fd652021-01-15 22:13:04 -0800651 /* stay in paused until av_sync_pause(false) */
652 avsync->paused = true;
653 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
Song Zhaoea5a0412021-01-18 16:40:08 -0800654 log_info ("[%d]reach pause pts: %u",
655 avsync->session_id, avsync->last_frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800656 }
657
658exit:
659 pthread_mutex_unlock(&avsync->lock);
660 if (avsync->last_frame) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800661 if (enter_last_frame != avsync->last_frame)
662 log_debug("[%d]pop %u", avsync->session_id, avsync->last_frame->pts);
Song Zhao35a82df2021-04-15 10:58:49 -0700663 log_trace("[%d]pop %u", avsync->session_id, avsync->last_frame->pts);
Song Zhao065800e2021-05-26 15:56:06 -0700664 /* don't update vpts for out_lier */
665 if (avsync->last_frame->duration != -1)
666 msync_session_update_vpts(avsync->fd, systime,
667 avsync->last_frame->pts, interval * avsync->delay);
Song Zhaoc03ba122020-12-23 21:54:02 -0800668 } else
Song Zhaoea5a0412021-01-18 16:40:08 -0800669 if (enter_last_frame != avsync->last_frame)
670 log_debug("[%d]pop (nil)", avsync->session_id);
671
Song Zhao35a82df2021-04-15 10:58:49 -0700672 avsync->last_poptime = systime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800673 if (avsync->last_frame)
674 avsync->last_frame->hold_period++;
675 return avsync->last_frame;
676}
677
Song Zhaoc03ba122020-12-23 21:54:02 -0800678static inline uint32_t abs_diff(uint32_t a, uint32_t b)
679{
Song Zhaoea5a0412021-01-18 16:40:08 -0800680 return (int)(a - b) > 0 ? a - b : b - a;
Song Zhaoc03ba122020-12-23 21:54:02 -0800681}
682
683static uint64_t time_diff (struct timeval *b, struct timeval *a)
684{
685 return (b->tv_sec - a->tv_sec)*1000000 + (b->tv_usec - a->tv_usec);
686}
687
Song Zhaoc03ba122020-12-23 21:54:02 -0800688static bool frame_expire(struct av_sync_session* avsync,
689 uint32_t systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800690 uint32_t interval,
Song Zhaoc03ba122020-12-23 21:54:02 -0800691 struct vframe * frame,
692 struct vframe * next_frame,
693 int toggle_cnt)
694{
695 uint32_t fpts = frame->pts;
696 bool expire = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800697 uint32_t pts_correction = avsync->delay * interval;
Song Zhaoc03ba122020-12-23 21:54:02 -0800698
699 if (avsync->paused && avsync->pause_pts == AV_SYNC_INVALID_PAUSE_PTS)
700 return false;
701
702 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
703 return true;
704
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700705 if (avsync->mode == AV_SYNC_MODE_FREE_RUN) {
706 /* render according to FPS */
707 if (!VALID_TS(avsync->last_r_syst) ||
708 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
709 avsync->last_r_syst = systime;
710 return true;
711 }
712 return false;
713 }
714
Song Zhaoc03ba122020-12-23 21:54:02 -0800715 if (!fpts) {
716 if (avsync->last_frame) {
717 /* try to accumulate duration as PTS */
718 fpts = avsync->vpts + avsync->last_frame->duration;
719 } else {
720 fpts = avsync->vpts;
721 }
722 }
723 systime += pts_correction;
724
725 /* phase adjustment */
726 if (avsync->phase_set)
727 systime += avsync->phase;
728
Song Zhao35a82df2021-04-15 10:58:49 -0700729 log_trace("[%d]systime:%u phase:%u correct:%u fpts:%u",
Song Zhaoea5a0412021-01-18 16:40:08 -0800730 avsync->session_id, systime,
Song Zhao35a82df2021-04-15 10:58:49 -0700731 avsync->phase_set?avsync->phase:0, pts_correction, fpts);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700732 if (abs_diff(systime, fpts) > avsync->disc_thres_min) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800733 /* ignore discontinity under pause */
Song Zhaoea5a0412021-01-18 16:40:08 -0800734 if (avsync->paused)
Song Zhaoc03ba122020-12-23 21:54:02 -0800735 return false;
736
Song Zhaoa2985cb2021-06-24 12:01:47 -0700737 if ((VALID_TS(avsync->last_log_syst) && avsync->last_log_syst != systime) ||
738 (VALID_TS(avsync->last_pts) && avsync->last_pts != fpts)) {
Song Zhao5d2b4772021-01-18 16:40:08 -0800739 struct timeval now;
740
741 gettimeofday(&now, NULL);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700742 avsync->last_log_syst = systime;
Song Zhao5d2b4772021-01-18 16:40:08 -0800743 avsync->last_pts = fpts;
744 if (time_diff(&now, &avsync->sync_lost_print_time) >=
745 SYNC_LOST_PRINT_THRESHOLD) {
Song Zhaof46932e2021-05-21 01:51:45 -0700746 log_warn("[%d]sync lost systime:%u fpts:%u lost:%u",
Song Zhaoea5a0412021-01-18 16:40:08 -0800747 avsync->session_id, systime, fpts, avsync->sync_lost_cnt);
Song Zhao5d2b4772021-01-18 16:40:08 -0800748 avsync->sync_lost_cnt = 0;
Song Zhaobc6161d2021-03-08 09:59:33 -0800749 gettimeofday(&avsync->sync_lost_print_time, NULL);
Song Zhao5d2b4772021-01-18 16:40:08 -0800750 } else
751 avsync->sync_lost_cnt++;
752 }
Song Zhaod62bb392021-04-23 12:25:49 -0700753
754 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP &&
755 LIVE_MODE(avsync->mode) &&
Song Zhaoa2985cb2021-06-24 12:01:47 -0700756 VALID_TS(avsync->last_pts) &&
Song Zhao065800e2021-05-26 15:56:06 -0700757 abs_diff(avsync->last_pts, fpts) > STREAM_DISC_THRES) {
Song Zhaod62bb392021-04-23 12:25:49 -0700758 /* outlier by stream error */
759 avsync->outlier_cnt++;
Song Zhao065800e2021-05-26 15:56:06 -0700760 frame->duration = -1;
Song Zhaod62bb392021-04-23 12:25:49 -0700761 if (avsync->outlier_cnt < OUTLIER_MAX_CNT) {
762 log_info("render outlier %u", fpts);
763 return true;
764 }
765 }
766
767 avsync->outlier_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800768 avsync->state = AV_SYNC_STAT_SYNC_LOST;
769 avsync->phase_set = false;
Song Zhaoa58c3e92021-03-09 18:52:55 -0800770 reset_pattern(avsync->pattern_detector);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700771
772 if (LIVE_MODE(avsync->mode) && avsync->last_disc_pts != fpts) {
Song Zhaod62bb392021-04-23 12:25:49 -0700773 log_info ("[%d]video disc %u --> %u",
Song Zhaoa2985cb2021-06-24 12:01:47 -0700774 avsync->session_id, systime, fpts);
Song Zhao409739b2021-05-12 22:21:40 -0700775 msync_session_set_video_dis(avsync->fd, fpts);
776 avsync->last_disc_pts = fpts;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700777 }
778
779 if ((int)(systime - fpts) > 0) {
780 if ((int)(systime - fpts) < avsync->disc_thres_max) {
781 /* catch up PCR */
Song Zhaof46932e2021-05-21 01:51:45 -0700782 return true;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700783 } else {
784 /* render according to FPS */
785 if (!VALID_TS(avsync->last_r_syst) ||
786 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
787 avsync->last_r_syst = systime;
788 return true;
789 }
790 return false;
791 }
792 } else if (LIVE_MODE(avsync->mode)) {
793 /* hold if the gap is small */
794 if ((int)(fpts - systime) < avsync->disc_thres_max) {
795 return false;
796 } else {
797 /* render according to FPS */
798 if (!VALID_TS(avsync->last_r_syst) ||
799 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
800 avsync->last_r_syst = systime;
801 return true;
802 }
803 return false;
804 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800805 }
806 }
807
Song Zhao52f55192021-05-06 10:52:21 -0700808 /* In some cases, keeping pattern will enlarge the gap */
809 if (abs_diff(systime, fpts) > AV_PATTERN_RESET_THRES &&
810 avsync->first_frame_toggled) {
811 reset_pattern(avsync->pattern_detector);
Song Zhaof46932e2021-05-21 01:51:45 -0700812 log_warn("sync pattern reset sys:%u fpts:%u",
Song Zhao52f55192021-05-06 10:52:21 -0700813 systime, fpts);
814 }
815
Song Zhaoc03ba122020-12-23 21:54:02 -0800816 expire = (int)(systime - fpts) >= 0;
817
818 /* scatter the frame in different vsync whenever possible */
819 if (expire && next_frame && next_frame->pts && toggle_cnt) {
820 /* multi frame expired in current vsync but no frame in next vsync */
Song Zhaoea5a0412021-01-18 16:40:08 -0800821 if (systime + interval < next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800822 expire = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800823 log_debug("[%d]unset expire systime:%d inter:%d next_pts:%d toggle_cnt:%d",
824 avsync->session_id, systime, interval, next_frame->pts, toggle_cnt);
Song Zhaoc03ba122020-12-23 21:54:02 -0800825 }
826 } else if (!expire && next_frame && next_frame->pts && !toggle_cnt
827 && avsync->first_frame_toggled) {
828 /* next vsync will have at least 2 frame expired */
Song Zhao35a82df2021-04-15 10:58:49 -0700829 if (systime + interval >= next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800830 expire = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800831 log_debug("[%d]set expire systime:%d inter:%d next_pts:%d",
832 avsync->session_id, systime, interval, next_frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800833 }
834 }
835
Song Zhaoa58c3e92021-03-09 18:52:55 -0800836 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP)
837 correct_pattern(avsync->pattern_detector, frame, next_frame,
838 (avsync->last_frame?avsync->last_frame->hold_period:0),
839 avsync->last_holding_peroid, systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800840 interval, &expire);
Song Zhaoc03ba122020-12-23 21:54:02 -0800841
842 if (expire) {
843 avsync->vpts = fpts;
844 /* phase adjustment */
845 if (!avsync->phase_set) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800846 uint32_t phase_thres = interval / 4;
Song Zhaoc03ba122020-12-23 21:54:02 -0800847 if ( systime > fpts && (systime - fpts) < phase_thres) {
848 /* too aligned to current VSYNC, separate them to 1/4 VSYNC */
849 avsync->phase += phase_thres - (systime - fpts);
850 avsync->phase_set = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800851 log_info("[%d]adjust phase to %d", avsync->session_id, avsync->phase);
Song Zhaoc03ba122020-12-23 21:54:02 -0800852 }
853 if (!avsync->phase_set && systime > fpts &&
Song Zhaoea5a0412021-01-18 16:40:08 -0800854 systime < (fpts + interval) &&
855 (systime - fpts) > interval - phase_thres) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800856 /* too aligned to previous VSYNC, separate them to 1/4 VSYNC */
Song Zhaoea5a0412021-01-18 16:40:08 -0800857 avsync->phase += phase_thres + fpts + interval - systime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800858 avsync->phase_set = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800859 log_info("[%d]adjust phase to %d", avsync->session_id, avsync->phase);
Song Zhaoc03ba122020-12-23 21:54:02 -0800860 }
861 }
862
863 if (avsync->state != AV_SYNC_STAT_SYNC_SETUP)
Song Zhaoea5a0412021-01-18 16:40:08 -0800864 log_info("[%d]sync setup", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800865 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhao5d2b4772021-01-18 16:40:08 -0800866 avsync->sync_lost_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800867 }
868 return expire;
869}
870
Song Zhao35a82df2021-04-15 10:58:49 -0700871static bool pattern_detect(struct av_sync_session* avsync, int cur_period, int last_period)
Song Zhaoc03ba122020-12-23 21:54:02 -0800872{
Song Zhao35a82df2021-04-15 10:58:49 -0700873 bool ret = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800874 log_trace("[%d]cur_period: %d last_period: %d",
875 avsync->session_id, cur_period, last_period);
Song Zhao35a82df2021-04-15 10:58:49 -0700876 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P32, cur_period, last_period))
877 ret = true;
878 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P22, cur_period, last_period))
879 ret = true;
880 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P41, cur_period, last_period))
881 ret = true;
882 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P11, cur_period, last_period))
883 ret = true;
884
885 return ret;
Song Zhaoc03ba122020-12-23 21:54:02 -0800886}
887
888int av_sync_set_speed(void *sync, float speed)
889{
890 struct av_sync_session *avsync = (struct av_sync_session *)sync;
891
892 if (speed < 0.001f || speed > 100) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800893 log_error("[%d]wrong speed %f [0.0001, 100]", avsync->session_id, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -0800894 return -1;
895 }
896
Song Zhaoea5a0412021-01-18 16:40:08 -0800897 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER ||
898 avsync->mode == AV_SYNC_MODE_IPTV) {
899 log_info("[%d]ignore set speed in mode %d", avsync->session_id, avsync->mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800900 return 0;
Song Zhaoea5a0412021-01-18 16:40:08 -0800901 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800902
Song Zhaoea5a0412021-01-18 16:40:08 -0800903 avsync->speed = speed;
904
905 if (avsync->type == AV_SYNC_TYPE_AUDIO) {
906 if (speed == 1.0) {
907 avsync->mode = avsync->backup_mode;
908 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
909 } else {
910 avsync->backup_mode = avsync->mode;
911 avsync->mode = AV_SYNC_MODE_FREE_RUN;
912 log_info("[%d]audio to freerun mode", avsync->session_id);
913 }
914 }
915#if 0
Song Zhaoc03ba122020-12-23 21:54:02 -0800916 if (avsync->mode != AV_SYNC_MODE_VMASTER) {
917 log_info("ignore set speed in mode %d", avsync->mode);
918 return 0;
919 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800920#endif
Song Zhaoc03ba122020-12-23 21:54:02 -0800921
Song Zhaoea5a0412021-01-18 16:40:08 -0800922 log_info("session[%d] set rate to %f", avsync->session_id, speed);
923 return msync_session_set_rate(avsync->fd, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -0800924}
925
926int av_sync_change_mode(void *sync, enum sync_mode mode)
927{
928 struct av_sync_session *avsync = (struct av_sync_session *)sync;
929
930 if (!avsync)
931 return -1;
932
Song Zhaoea5a0412021-01-18 16:40:08 -0800933 if (msync_session_set_mode(avsync->fd, mode)) {
934 log_error("[%d]fail to set mode %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800935 return -1;
936 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800937 avsync->mode = mode;
Song Zhaoea5a0412021-01-18 16:40:08 -0800938 log_info("[%d]update sync mode to %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800939 return 0;
940}
941
Song Zhao01031bb2021-05-13 21:23:20 -0700942int av_sync_get_mode(void *sync, enum sync_mode *mode)
943{
944 struct av_sync_session *avsync = (struct av_sync_session *)sync;
945
946 if (!avsync || !mode)
947 return -1;
948
949 *mode = avsync->mode;
950 return 0;
951}
952
Song Zhaoc03ba122020-12-23 21:54:02 -0800953int av_sync_set_pause_pts(void *sync, pts90K pts)
954{
955 struct av_sync_session *avsync = (struct av_sync_session *)sync;
956
957 if (!avsync)
958 return -1;
959
960 avsync->pause_pts = pts;
Song Zhaoea5a0412021-01-18 16:40:08 -0800961 log_info("[%d]set pause pts: %u", avsync->session_id, pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800962 return 0;
963}
964
965int av_sync_set_pause_pts_cb(void *sync, pause_pts_done cb, void *priv)
966{
967 struct av_sync_session *avsync = (struct av_sync_session *)sync;
968
969 if (!avsync)
970 return -1;
971
972 avsync->pause_pts_cb = cb;
973 avsync->pause_cb_priv = priv;
974 return 0;
975}
Song Zhaoea5a0412021-01-18 16:40:08 -0800976
977static void trigger_audio_start_cb(struct av_sync_session *avsync,
978 avs_ascb_reason reason)
979{
980 if (avsync) {
981 pthread_mutex_lock(&avsync->lock);
982 if (avsync->audio_start) {
983 avsync->audio_start(avsync->audio_start_priv, reason);
984 avsync->session_started = true;
985 avsync->audio_start = NULL;
986 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
987 }
988 pthread_mutex_unlock(&avsync->lock);
989 }
990}
991
992avs_start_ret av_sync_audio_start(
993 void *sync,
994 pts90K pts,
995 pts90K delay,
996 audio_start_cb cb,
997 void *priv)
998{
999 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1000 uint32_t start_mode;
1001 avs_start_ret ret = AV_SYNC_ASTART_ERR;
1002 bool create_poll_t = false;
1003
1004 if (!avsync)
1005 return ret;
1006
1007 if (msync_session_set_audio_start(avsync->fd, pts, delay, &start_mode))
1008 log_error("[%d]fail to set audio start", avsync->session_id);
1009
yongchun.li107a6162021-05-05 02:38:57 -07001010 if (avsync->in_audio_switch
1011 && avsync->audio_switch_state == AUDIO_SWITCH_STAT_RESET) {
1012 log_info("%d audio_switch_state to start start mode %d",
1013 avsync->session_id, start_mode);
1014 avsync->audio_switch_state = AUDIO_SWITCH_STAT_START;
1015 }
1016
Song Zhaoea5a0412021-01-18 16:40:08 -08001017 if (start_mode == AVS_START_SYNC) {
1018 ret = AV_SYNC_ASTART_SYNC;
1019 avsync->session_started = true;
Song Zhao065800e2021-05-26 15:56:06 -07001020 avsync->state = AV_SYNC_STAT_RUNNING;
Song Zhaod62bb392021-04-23 12:25:49 -07001021 } else if (start_mode == AVS_START_ASYNC) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001022 ret = AV_SYNC_ASTART_ASYNC;
Song Zhaod62bb392021-04-23 12:25:49 -07001023 avsync->state = AV_SYNC_STAT_RUNNING;
1024 } else if (start_mode == AVS_START_AGAIN) {
1025 ret = AV_SYNC_ASTART_AGAIN;
1026 }
1027
1028 if (ret == AV_SYNC_ASTART_AGAIN)
1029 goto exit;
Song Zhaoea5a0412021-01-18 16:40:08 -08001030
yongchun.li107a6162021-05-05 02:38:57 -07001031 if (avsync->mode == AV_SYNC_MODE_AMASTER || avsync->in_audio_switch) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001032 create_poll_t = true;
1033 if (start_mode == AVS_START_ASYNC) {
1034 if (!cb) {
1035 log_error("[%d]invalid cb", avsync->session_id);
1036 return AV_SYNC_ASTART_ERR;
1037 }
1038 avsync->audio_start = cb;
1039 avsync->audio_start_priv = priv;
1040 }
Song Zhaod62bb392021-04-23 12:25:49 -07001041 } else if (LIVE_MODE(avsync->mode))
Song Zhaoea5a0412021-01-18 16:40:08 -08001042 create_poll_t = true;
1043
Song Zhaod62bb392021-04-23 12:25:49 -07001044 if (create_poll_t && !avsync->poll_thread) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001045 int ret;
1046
1047 log_info("[%d]start poll thread", avsync->session_id);
1048 avsync->quit_poll = false;
1049 ret = pthread_create(&avsync->poll_thread, NULL, poll_thread, avsync);
1050 if (ret) {
1051 log_error("[%d]create poll thread errno %d", avsync->session_id, errno);
1052 return AV_SYNC_ASTART_ERR;
1053 }
1054 }
Song Zhaod62bb392021-04-23 12:25:49 -07001055 if (LIVE_MODE(avsync->mode)) {
1056 uint32_t systime;
1057 msync_session_get_wall(avsync->fd, &systime, NULL);
1058 log_info("[%d]return %u w %u pts %u d %u",
1059 avsync->session_id, ret, systime, pts, delay);
1060 }
1061exit:
Song Zhaoea5a0412021-01-18 16:40:08 -08001062 log_info("[%d]return %u", avsync->session_id, ret);
1063 return ret;
1064}
1065
1066int av_sync_audio_render(
1067 void *sync,
1068 pts90K pts,
1069 struct audio_policy *policy)
1070{
1071 int ret = 0;
Song Zhao065800e2021-05-26 15:56:06 -07001072 bool out_lier = false;
Song Zhaoea5a0412021-01-18 16:40:08 -08001073 uint32_t systime;
1074 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1075 avs_audio_action action = AA_SYNC_AA_MAX;
1076
1077 if (!avsync || !policy)
1078 return -1;
1079
yongchun.li107a6162021-05-05 02:38:57 -07001080 msync_session_get_wall(avsync->fd, &systime, NULL);
1081
1082 log_trace("audio render pts %u, systime %u, mode %u diff ms %d",
1083 pts, systime, avsync->mode, (int)(pts-systime)/90);
1084
1085 if (avsync->in_audio_switch
1086 && avsync->audio_switch_state == AUDIO_SWITCH_STAT_START) {
1087 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_HB) {
1088 log_info("Audio pts in system range sys %u pts %u\n", systime, pts);
1089 avsync->audio_switch_state = AUDIO_SWITCH_STAT_FINISH;
1090 action = AV_SYNC_AA_RENDER;
1091 } else if ((int)(systime - pts) > 0) {
1092 log_info("[%d] audio change drop %d ms sys %u pts %u", avsync->session_id,
1093 (int)(systime - pts)/90, systime, pts);
1094 action = AV_SYNC_AA_DROP;
1095 } else {
1096 action = AV_SYNC_AA_INSERT;
1097 log_info("[%d] audio change insert %d ms sys %u pts %u", avsync->session_id,
1098 (int)(pts - systime)/90, systime, pts);
1099 }
1100 goto done;
1101 }
1102
Song Zhaoea5a0412021-01-18 16:40:08 -08001103 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
1104 avsync->mode == AV_SYNC_MODE_AMASTER) {
1105 action = AV_SYNC_AA_RENDER;
1106 goto done;
1107 }
1108
Song Zhaod62bb392021-04-23 12:25:49 -07001109 /* stopping procedure, unblock audio rendering */
1110 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER &&
1111 avsync->active_mode == AV_SYNC_MODE_FREE_RUN) {
1112 action = AV_SYNC_AA_DROP;
1113 goto done;
1114 }
1115
Song Zhao7daf3a12021-05-10 22:22:25 -07001116 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
1117 avsync->mode == AV_SYNC_MODE_AMASTER) {
1118 action = AV_SYNC_AA_RENDER;
1119 goto done;
1120 }
1121
Song Zhaod62bb392021-04-23 12:25:49 -07001122 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP &&
1123 LIVE_MODE(avsync->mode) &&
1124 abs_diff(systime, pts) > STREAM_DISC_THRES) {
1125 /* outlier by stream error */
1126 avsync->outlier_cnt++;
1127 if (avsync->outlier_cnt > OUTLIER_MAX_CNT) {
1128 /* treat as disc, just drop current frame */
1129 avsync->state = AV_SYNC_STAT_SYNC_LOST;
1130 avsync->outlier_cnt = 0;
1131 action = AV_SYNC_AA_DROP;
1132 systime = pts;
Song Zhaod62bb392021-04-23 12:25:49 -07001133 goto done;
1134 }
1135 log_info("[%d]ignore outlier %u", avsync->session_id, pts);
1136 pts = systime;
1137 action = AV_SYNC_AA_RENDER;
Song Zhao065800e2021-05-26 15:56:06 -07001138 out_lier = true;
Song Zhaod62bb392021-04-23 12:25:49 -07001139 goto done;
1140 }
1141
1142 avsync->outlier_cnt = 0;
1143 /* low bound from sync_lost to sync_setup */
1144 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_LB) {
1145 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
1146 action = AV_SYNC_AA_RENDER;
1147 goto done;
1148 }
1149
1150 /* high bound of sync_setup */
1151 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_HB &&
1152 avsync->state != AV_SYNC_STAT_SYNC_LOST) {
1153 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhaoea5a0412021-01-18 16:40:08 -08001154 action = AV_SYNC_AA_RENDER;
1155 goto done;
1156 }
1157
1158 if ((int)(systime - pts) > 0) {
Song Zhaod62bb392021-04-23 12:25:49 -07001159 avsync->state = AV_SYNC_STAT_SYNC_LOST;
Song Zhaoea5a0412021-01-18 16:40:08 -08001160 action = AV_SYNC_AA_DROP;
1161 goto done;
1162 }
1163
1164 if ((int)(systime - pts) < 0) {
Song Zhaod62bb392021-04-23 12:25:49 -07001165 avsync->state = AV_SYNC_STAT_SYNC_LOST;
Song Zhaoea5a0412021-01-18 16:40:08 -08001166 action = AV_SYNC_AA_INSERT;
1167 goto done;
1168 }
1169
1170done:
1171 policy->action = action;
1172 policy->delta = (int)(systime - pts);
1173 if (action == AV_SYNC_AA_RENDER) {
1174 avsync->apts = pts;
yongchun.li107a6162021-05-05 02:38:57 -07001175 if (!avsync->in_audio_switch) {
Song Zhao065800e2021-05-26 15:56:06 -07001176 if (!out_lier)
1177 msync_session_update_apts(avsync->fd, systime, pts, 0);
Song Zhaof46932e2021-05-21 01:51:45 -07001178 log_debug("[%d]return %d sys %u - pts %u = %d",
Song Zhao409739b2021-05-12 22:21:40 -07001179 avsync->session_id, action, systime, pts, systime - pts);
yongchun.li107a6162021-05-05 02:38:57 -07001180 } else if(avsync->audio_switch_state == AUDIO_SWITCH_STAT_FINISH) {
1181 msync_session_update_apts(avsync->fd, systime, pts, 0);
1182 log_info("[%d] audio switch done sys %u pts %u",
1183 avsync->session_id, systime, pts);
1184 msync_session_set_audio_switch(avsync->fd, false);
1185 avsync->in_audio_switch = false;
1186 avsync->audio_switch_state = AUDIO_SWITCH_STAT_INIT;
1187 } else {
1188 log_trace("[%d] in audio switch ret %d sys %u - pts %u = %d",
1189 avsync->session_id, action, systime, pts, systime - pts);
1190 }
Song Zhaoa2985cb2021-06-24 12:01:47 -07001191 avsync->audio_drop_cnt = 0;
Song Zhaoea5a0412021-01-18 16:40:08 -08001192 } else {
Song Zhaoa2985cb2021-06-24 12:01:47 -07001193 if (abs_diff(systime, pts) > avsync->disc_thres_min &&
yongchun.li085b5a42021-05-24 04:22:53 -07001194 avsync->last_disc_pts != pts &&
1195 !avsync->in_audio_switch) {
Song Zhao409739b2021-05-12 22:21:40 -07001196 log_info ("[%d]audio disc %u --> %u",
1197 avsync->session_id, systime, pts);
1198 msync_session_set_audio_dis(avsync->fd, pts);
1199 avsync->last_disc_pts = pts;
Song Zhaoa2985cb2021-06-24 12:01:47 -07001200 } else if (action == AV_SYNC_AA_DROP) {
1201 struct timeval now;
1202
1203 /* dropping recovery */
1204 gettimeofday(&now, NULL);
1205 if (!avsync->audio_drop_cnt)
1206 avsync->audio_drop_start = now;
1207 avsync->audio_drop_cnt++;
1208 if (time_diff(&now, &avsync->audio_drop_start) > 500000) {
1209 log_info ("[%d]audio keep dropping sys %u vs a %u",
1210 avsync->session_id, systime, pts);
1211 msync_session_set_audio_dis(avsync->fd, pts);
1212 }
Song Zhao409739b2021-05-12 22:21:40 -07001213 }
Song Zhaoa2985cb2021-06-24 12:01:47 -07001214 if (action != AV_SYNC_AA_DROP)
1215 avsync->audio_drop_cnt = 0;
Song Zhaof46932e2021-05-21 01:51:45 -07001216 log_debug("[%d]return %d sys %u - pts %u = %d",
Song Zhaod62bb392021-04-23 12:25:49 -07001217 avsync->session_id, action, systime, pts, systime - pts);
Song Zhaoea5a0412021-01-18 16:40:08 -08001218 }
1219
1220 return ret;
1221}
1222
1223int av_sync_get_clock(void *sync, pts90K *pts)
1224{
1225 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1226
1227 if (!avsync || !pts)
1228 return -1;
1229 return msync_session_get_wall(avsync->fd, pts, NULL);
1230}
1231
1232static void handle_mode_change_a(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -07001233 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -08001234{
Song Zhaoe208d692021-04-19 15:38:52 -07001235 log_info("[%d]amode %d mode %d v/a/vt %d/%d/%d", avsync->session_id,
1236 avsync->active_mode, avsync->mode, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -08001237 if (avsync->active_mode == AV_SYNC_MODE_AMASTER) {
1238 float speed;
1239 if (avsync->start_policy == AV_SYNC_START_ALIGN &&
Song Zhaoe208d692021-04-19 15:38:52 -07001240 a_active && avsync->audio_start) {
yongchun.li107a6162021-05-05 02:38:57 -07001241 if (v_active || v_timeout || avsync->in_audio_switch) {
Song Zhaoe208d692021-04-19 15:38:52 -07001242 log_info("audio start cb");
1243 trigger_audio_start_cb(avsync, AV_SYNC_ASCB_OK);
yongchun.li107a6162021-05-05 02:38:57 -07001244 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001245 }
1246
1247 if (!msync_session_get_rate(avsync->fd, &speed)) {
1248 /* speed change is triggered by asink,
1249 * attached audio HAL will handle it
1250 */
1251 if (speed != avsync->speed)
1252 log_info("[%d]new rate %f", avsync->session_id, speed);
1253 if (speed == 1.0) {
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001254 if (avsync->mode != avsync->backup_mode) {
1255 avsync->mode = avsync->backup_mode;
1256 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
1257 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001258 } else {
1259 avsync->backup_mode = avsync->mode;
1260 avsync->mode = AV_SYNC_MODE_FREE_RUN;
1261 log_info("[%d]audio to freerun mode", avsync->session_id);
1262 }
1263 avsync->speed = speed;
1264 }
Song Zhaod62bb392021-04-23 12:25:49 -07001265 } else if (avsync->active_mode == AV_SYNC_MODE_PCR_MASTER) {
1266 struct session_debug debug;
1267 if (!msync_session_get_debug_mode(avsync->fd, &debug)) {
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001268 if (debug.debug_freerun && !avsync->debug_freerun) {
Song Zhaod62bb392021-04-23 12:25:49 -07001269 avsync->backup_mode = avsync->mode;
1270 avsync->mode = AV_SYNC_MODE_FREE_RUN;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001271 avsync->debug_freerun = true;
Song Zhaod62bb392021-04-23 12:25:49 -07001272 log_warn("[%d]audio to freerun mode", avsync->session_id);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001273 } else if (!debug.debug_freerun && avsync->debug_freerun) {
Song Zhaod62bb392021-04-23 12:25:49 -07001274 avsync->mode = avsync->backup_mode;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001275 avsync->debug_freerun = false;
Song Zhaod62bb392021-04-23 12:25:49 -07001276 log_warn("[%d]audio back to mode %d",
1277 avsync->session_id, avsync->mode);
1278 }
1279 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001280 }
1281}
1282
1283static void handle_mode_change_v(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -07001284 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -08001285{
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001286 struct session_debug debug;
1287
Song Zhaoea5a0412021-01-18 16:40:08 -08001288 log_info("[%d]amode mode %d %d v/a %d/%d", avsync->session_id,
1289 avsync->active_mode, avsync->mode, v_active, a_active);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001290 if (!msync_session_get_debug_mode(avsync->fd, &debug)) {
1291 if (debug.debug_freerun && !avsync->debug_freerun) {
1292 avsync->backup_mode = avsync->mode;
1293 avsync->mode = AV_SYNC_MODE_FREE_RUN;
1294 avsync->debug_freerun = true;
1295 log_warn("[%d]video to freerun mode", avsync->session_id);
1296 } else if (!debug.debug_freerun && avsync->debug_freerun) {
1297 avsync->mode = avsync->backup_mode;
1298 avsync->debug_freerun = false;
1299 log_warn("[%d]video back to mode %d",
1300 avsync->session_id, avsync->mode);
Song Zhaod62bb392021-04-23 12:25:49 -07001301 }
1302 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001303}
1304
1305static void * poll_thread(void * arg)
1306{
1307 int ret = 0;
1308 struct av_sync_session *avsync = (struct av_sync_session *)arg;
1309 const int fd = avsync->fd;
1310 struct pollfd pfd = {
1311 /* default blocking capture */
1312 .events = POLLIN | POLLRDNORM | POLLPRI | POLLOUT | POLLWRNORM,
1313 .fd = avsync->fd,
1314 };
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001315 enum src_flag sflag = SRC_A;
Song Zhaoea5a0412021-01-18 16:40:08 -08001316
1317 prctl (PR_SET_NAME, "avs_poll");
1318 log_info("[%d]enter", avsync->session_id);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001319
1320 if (avsync->type == AV_SYNC_TYPE_AUDIO)
1321 sflag = SRC_A;
1322 else if (avsync->type == AV_SYNC_TYPE_VIDEO)
1323 sflag = SRC_V;
1324
Song Zhaoea5a0412021-01-18 16:40:08 -08001325 while (!avsync->quit_poll) {
1326 for (;;) {
1327 ret = poll(&pfd, 1, 10);
1328 if (ret > 0)
1329 break;
1330 if (avsync->quit_poll)
1331 goto exit;
1332 if (errno == EINTR)
1333 continue;
1334 }
1335
1336 /* error handling */
1337 if (pfd.revents & POLLERR)
1338 log_error("[%d]POLLERR received", avsync->session_id);
1339
Song Zhaod62bb392021-04-23 12:25:49 -07001340 /* mode change. Non-exclusive wait so all the processes
1341 * shall be woken up
1342 */
Song Zhaoea5a0412021-01-18 16:40:08 -08001343 if (pfd.revents & POLLPRI) {
Song Zhaoe208d692021-04-19 15:38:52 -07001344 bool v_active, a_active, v_timeout;
Song Zhaoea5a0412021-01-18 16:40:08 -08001345
1346 msync_session_get_stat(fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001347 &v_active, &a_active, &v_timeout, &avsync->in_audio_switch, sflag);
Song Zhaoea5a0412021-01-18 16:40:08 -08001348
1349 if (avsync->type == AV_SYNC_TYPE_AUDIO)
Song Zhaoe208d692021-04-19 15:38:52 -07001350 handle_mode_change_a(avsync, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -08001351 else if (avsync->type == AV_SYNC_TYPE_VIDEO)
Song Zhaoe208d692021-04-19 15:38:52 -07001352 handle_mode_change_v(avsync, v_active, a_active, v_timeout);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001353 usleep(10000);
Song Zhaoea5a0412021-01-18 16:40:08 -08001354 }
1355 }
1356exit:
1357 log_info("[%d]quit", avsync->session_id);
1358 return NULL;
1359}
1360
Song Zhaod62bb392021-04-23 12:25:49 -07001361int av_sync_set_pcr_clock(void *sync, pts90K pts, uint64_t mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -08001362{
1363 struct av_sync_session *avsync = (struct av_sync_session *)sync;
wei.dubcc2ed22021-05-19 07:16:10 -04001364 struct pcr_info pcr;
1365 enum pcr_monitor_status status;
1366 int ppm;
Song Zhaoea5a0412021-01-18 16:40:08 -08001367 if (!avsync)
1368 return -1;
1369
1370 if (avsync->type != AV_SYNC_TYPE_PCR)
1371 return -2;
1372
wei.dubcc2ed22021-05-19 07:16:10 -04001373 pcr.monoclk = mono_clock / 1000;
1374 pcr.pts = (long long) pts * 1000 / 90;
1375 pcr_monitor_process(avsync->pcr_monitor, &pcr);
1376
1377 status = pcr_monitor_get_status(avsync->pcr_monitor);
1378
1379 if (status >= DEVIATION_READY) {
1380 pcr_monitor_get_deviation(avsync->pcr_monitor, &ppm);
1381 if (avsync->ppm != ppm) {
1382 avsync->ppm = ppm;
1383 log_info("[%d]ppm:%d", avsync->session_id, ppm);
1384 if (msync_session_set_clock_dev(avsync->fd, ppm))
1385 log_error("set clock dev fail");
1386 }
1387 }
1388
Song Zhaod62bb392021-04-23 12:25:49 -07001389 return msync_session_set_pcr(avsync->fd, pts, mono_clock);
Song Zhaoea5a0412021-01-18 16:40:08 -08001390}
1391
Song Zhaod62bb392021-04-23 12:25:49 -07001392int av_sync_get_pcr_clock(void *sync, pts90K *pts, uint64_t * mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -08001393{
1394 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1395
1396 if (!avsync)
1397 return -1;
1398
Song Zhaod62bb392021-04-23 12:25:49 -07001399 return msync_session_get_pcr(avsync->fd, pts, mono_clock);
Song Zhaoea5a0412021-01-18 16:40:08 -08001400}
1401
1402int av_sync_set_session_name(void *sync, const char *name)
1403{
1404 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1405
1406 if (!avsync)
1407 return -1;
1408
1409 return msync_session_set_name(avsync->fd, name);
1410}
yongchun.li107a6162021-05-05 02:38:57 -07001411
1412int av_sync_set_audio_switch(void *sync, bool start)
1413{
1414 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1415 bool v_active, a_active, v_timeout;
1416
1417 if (!avsync)
1418 return -1;
1419 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
1420 &v_active, &a_active,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001421 &v_timeout, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -07001422 log_error("[%d] can not get session state",
1423 avsync->session_id);
1424 return -1;
1425 }
1426 if (!v_active || !a_active) {
1427 log_error("[%d] no apply if not AV both active v %d a %d",
1428 avsync->session_id, v_active, a_active);
1429 return -1;
1430 }
1431 if (msync_session_set_audio_switch(avsync->fd, start)) {
1432 log_error("[%d]fail to set audio switch %d", avsync->session_id, start);
1433 return -1;
1434 }
1435 avsync->in_audio_switch = start;
1436 avsync->audio_switch_state = AUDIO_SWITCH_STAT_INIT;
1437 log_info("[%d]update audio switch to %d", avsync->session_id, start);
1438 return 0;
1439}
1440
1441int av_sync_get_audio_switch(void *sync, bool *start)
1442{
1443 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1444
1445 if (!avsync)
1446 return -1;
1447 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001448 NULL, NULL, NULL, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -07001449 log_error("[%d] can not audio seamless switch state",
1450 avsync->session_id);
1451 return -1;
1452 }
1453 if (start) *start = avsync->in_audio_switch;
1454 return 0;
Song Zhao7daf3a12021-05-10 22:22:25 -07001455}
Song Zhao8039f562021-05-18 18:11:25 -07001456
1457enum clock_recovery_stat av_sync_get_clock_devication(void *sync, int32_t *ppm)
1458{
1459 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1460
wei.dubcc2ed22021-05-19 07:16:10 -04001461 if (!avsync || !ppm)
1462 return CLK_RECOVERY_ERR;
1463 if (avsync->mode != AV_SYNC_MODE_PCR_MASTER)
Song Zhao8039f562021-05-18 18:11:25 -07001464 return CLK_RECOVERY_NOT_RUNNING;
1465
wei.dubcc2ed22021-05-19 07:16:10 -04001466 if (msync_session_get_clock_dev(avsync->fd, ppm))
1467 return CLK_RECOVERY_ERR;
1468
1469 if (*ppm == 0)
1470 return CLK_RECOVERY_ONGOING;
1471 else
1472 return CLK_RECOVERY_READY;
Song Zhao8039f562021-05-18 18:11:25 -07001473}