blob: f07fb5feb51412f3e47341e9e3bcb66882b650ba [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"
Song Zhao4f632952021-12-16 09:00:18 -080025#include "aml_queue.h"
Song Zhaoc03ba122020-12-23 21:54:02 -080026#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 Zhao2f6744b2021-11-03 21:23:50 -070032
Song Zhaoc03ba122020-12-23 21:54:02 -080033enum sync_state {
34 AV_SYNC_STAT_INIT = 0,
35 AV_SYNC_STAT_RUNNING = 1,
36 AV_SYNC_STAT_SYNC_SETUP = 2,
37 AV_SYNC_STAT_SYNC_LOST = 3,
38};
39
yongchun.li107a6162021-05-05 02:38:57 -070040enum audio_switch_state_ {
41 AUDIO_SWITCH_STAT_INIT = 0,
42 AUDIO_SWITCH_STAT_RESET = 1,
43 AUDIO_SWITCH_STAT_START = 2,
44 AUDIO_SWITCH_STAT_FINISH = 3,
yongchun.li59e873d2021-07-07 11:42:38 -070045 AUDIO_SWITCH_STAT_AGAIN = 4,
yongchun.li107a6162021-05-05 02:38:57 -070046};
47
Song Zhaoea5a0412021-01-18 16:40:08 -080048#define SESSION_DEV "avsync_s"
49
Song Zhaoc03ba122020-12-23 21:54:02 -080050struct av_sync_session {
51 /* session id attached */
52 int session_id;
Song Zhaoea5a0412021-01-18 16:40:08 -080053 int fd;
54 bool attached;
55 enum sync_mode mode;
56 /* for audio trickplay */
57 enum sync_mode backup_mode;
58 enum sync_type type;
59 uint32_t start_policy;
bo.xiao5821fc72021-07-11 22:47:00 -040060 int timeout;
Song Zhaoc03ba122020-12-23 21:54:02 -080061
Song Zhaoea5a0412021-01-18 16:40:08 -080062 /* playback time, will stop increasing during pause */
63 pts90K vpts;
64 pts90K apts;
65
66 /* phase adjustment of stream time for rate control (Video ONLY) */
Song Zhaoc03ba122020-12-23 21:54:02 -080067 pts90K phase;
68 bool phase_set;
69
70 /* pts of last rendered frame */
Song Zhaoea5a0412021-01-18 16:40:08 -080071 pts90K last_wall;
Song Zhaoc03ba122020-12-23 21:54:02 -080072 pts90K last_pts;
73 struct vframe *last_frame;
74
Song Zhaoe0bf6ad2021-07-09 11:28:42 -070075 /* pts of last pushed frame */
76 pts90K last_q_pts;
77
Song Zhaoc03ba122020-12-23 21:54:02 -080078 bool first_frame_toggled;
Song Zhaoc03ba122020-12-23 21:54:02 -080079 bool paused;
Song Zhaoea5a0412021-01-18 16:40:08 -080080 enum sync_state state;
Song Zhaoc03ba122020-12-23 21:54:02 -080081 void *pattern_detector;
82 void *frame_q;
Song Zhaoc03ba122020-12-23 21:54:02 -080083
Song Zhaoea5a0412021-01-18 16:40:08 -080084 /* start control */
85 int start_thres;
86 audio_start_cb audio_start;
87 void *audio_start_priv;
88
89 /* render property */
Song Zhaoc03ba122020-12-23 21:54:02 -080090 int delay;
91 pts90K vsync_interval;
92
93 /* state lock */
94 pthread_mutex_t lock;
95 /* pattern */
96 int last_holding_peroid;
Song Zhaoea5a0412021-01-18 16:40:08 -080097 bool session_started;
Song Zhaoc03ba122020-12-23 21:54:02 -080098
99 float speed;
100
Song Zhaoc03ba122020-12-23 21:54:02 -0800101 /* pause pts */
102 pts90K pause_pts;
103 pause_pts_done pause_pts_cb;
104 void *pause_cb_priv;
Song Zhao5d2b4772021-01-18 16:40:08 -0800105
106 /* log control */
Song Zhaoa2985cb2021-06-24 12:01:47 -0700107 uint32_t last_log_syst;
Song Zhao5d2b4772021-01-18 16:40:08 -0800108 uint32_t sync_lost_cnt;
yongchun.li0ee6e372021-08-20 04:26:04 -0700109 struct timespec sync_lost_print_time;
Song Zhaoea5a0412021-01-18 16:40:08 -0800110
111 pthread_t poll_thread;
112 /* pcr master, IPTV only */
113 bool quit_poll;
114 enum sync_mode active_mode;
Song Zhaof46932e2021-05-21 01:51:45 -0700115 uint32_t disc_thres_min;
116 uint32_t disc_thres_max;
Song Zhao35a82df2021-04-15 10:58:49 -0700117
118 /* error detection */
119 uint32_t last_poptime;
Song Zhaod62bb392021-04-23 12:25:49 -0700120 uint32_t outlier_cnt;
Song Zhao409739b2021-05-12 22:21:40 -0700121 pts90K last_disc_pts;
122
yongchun.li107a6162021-05-05 02:38:57 -0700123 // indicate set audio switch
124 bool in_audio_switch;
125 enum audio_switch_state_ audio_switch_state;
wei.dubcc2ed22021-05-19 07:16:10 -0400126
127 //pcr monitor handle
128 void *pcr_monitor;
129 int ppm;
Song Zhao623e2f12021-09-03 15:54:04 -0700130 bool ppm_adjusted;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700131
132 //video FPS detection
133 pts90K last_fpts;
134 int fps_interval;
135 int fps_interval_acc;
136 int fps_cnt;
137
138 //video freerun with rate control
139 uint32_t last_r_syst;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700140 bool debug_freerun;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700141
142 //Audio dropping detection
143 uint32_t audio_drop_cnt;
yongchun.li0ee6e372021-08-20 04:26:04 -0700144 struct timespec audio_drop_start;
Song Zhao95bd0922021-09-21 14:07:46 -0700145
146 /*system mono time for current vsync interrupt */
147 uint64_t msys;
Song Zhaoc03ba122020-12-23 21:54:02 -0800148};
149
150#define MAX_FRAME_NUM 32
151#define DEFAULT_START_THRESHOLD 2
152#define TIME_UNIT90K (90000)
Song Zhaof46932e2021-05-21 01:51:45 -0700153#define AV_DISC_THRES_MIN (TIME_UNIT90K / 3)
154#define AV_DISC_THRES_MAX (TIME_UNIT90K * 10)
Song Zhao7daf3a12021-05-10 22:22:25 -0700155#define A_ADJ_THREDHOLD_HB (900 * 6) //60ms
156#define A_ADJ_THREDHOLD_LB (900 * 2) //20ms
Song Zhao52f55192021-05-06 10:52:21 -0700157#define AV_PATTERN_RESET_THRES (TIME_UNIT90K / 10)
Song Zhao5d2b4772021-01-18 16:40:08 -0800158#define SYNC_LOST_PRINT_THRESHOLD 10000000 //10 seconds In micro seconds
Song Zhaod62bb392021-04-23 12:25:49 -0700159#define LIVE_MODE(mode) ((mode) == AV_SYNC_MODE_PCR_MASTER || (mode) == AV_SYNC_MODE_IPTV)
160
Song Zhao065800e2021-05-26 15:56:06 -0700161#define STREAM_DISC_THRES (TIME_UNIT90K / 10)
Song Zhaod62bb392021-04-23 12:25:49 -0700162#define OUTLIER_MAX_CNT 8
Song Zhaoa2985cb2021-06-24 12:01:47 -0700163#define VALID_TS(x) ((x) != -1)
Song Zhaoc03ba122020-12-23 21:54:02 -0800164
yongchun.li0ee6e372021-08-20 04:26:04 -0700165static uint64_t time_diff (struct timespec *b, struct timespec *a);
Song Zhaoc03ba122020-12-23 21:54:02 -0800166static bool frame_expire(struct av_sync_session* avsync,
167 uint32_t systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800168 uint32_t interval,
Song Zhaoc03ba122020-12-23 21:54:02 -0800169 struct vframe * frame,
170 struct vframe * next_frame,
171 int toggle_cnt);
Song Zhao35a82df2021-04-15 10:58:49 -0700172static bool pattern_detect(struct av_sync_session* avsync,
Song Zhaoc03ba122020-12-23 21:54:02 -0800173 int cur_period,
174 int last_period);
Song Zhaoea5a0412021-01-18 16:40:08 -0800175static void * poll_thread(void * arg);
176static void trigger_audio_start_cb(struct av_sync_session *avsync,
177 avs_ascb_reason reason);
Song Zhao95bd0922021-09-21 14:07:46 -0700178static struct vframe * video_mono_pop_frame(struct av_sync_session *avsync);
179static int video_mono_push_frame(struct av_sync_session *avsync, struct vframe *frame);
Song Zhao2f6744b2021-11-03 21:23:50 -0700180pthread_mutex_t glock = PTHREAD_MUTEX_INITIALIZER;
Song Zhaoc03ba122020-12-23 21:54:02 -0800181
Song Zhaoea5a0412021-01-18 16:40:08 -0800182int av_sync_open_session(int *session_id)
183{
Song Zhao2f6744b2021-11-03 21:23:50 -0700184 int fd = -1;
Song Zhaoea5a0412021-01-18 16:40:08 -0800185 int id, rc;
186
Song Zhao2f6744b2021-11-03 21:23:50 -0700187 pthread_mutex_lock(&glock);
188 fd = msync_create_session();
Song Zhaoea5a0412021-01-18 16:40:08 -0800189 if (fd < 0) {
190 log_error("fail");
Song Zhao2f6744b2021-11-03 21:23:50 -0700191 goto exit;
Song Zhaoea5a0412021-01-18 16:40:08 -0800192 }
193 rc = ioctl(fd, AMSYNC_IOC_ALLOC_SESSION, &id);
194 if (rc) {
195 log_error("new session errno:%d", errno);
Song Zhao2f6744b2021-11-03 21:23:50 -0700196 msync_destory_session(fd);
197 goto exit;
Song Zhaoea5a0412021-01-18 16:40:08 -0800198 }
199 *session_id = id;
Song Zhao2f6744b2021-11-03 21:23:50 -0700200 log_debug("new avsession id %d fd %d", id, fd);
201exit:
202 pthread_mutex_unlock(&glock);
Song Zhaoea5a0412021-01-18 16:40:08 -0800203 return fd;
204}
205
206void av_sync_close_session(int session)
207{
Song Zhao2f6744b2021-11-03 21:23:50 -0700208 log_debug("session closed fd %d", session);
209 pthread_mutex_lock(&glock);
Song Zhaoea5a0412021-01-18 16:40:08 -0800210 msync_destory_session(session);
Song Zhao2f6744b2021-11-03 21:23:50 -0700211 pthread_mutex_unlock(&glock);
Song Zhaoea5a0412021-01-18 16:40:08 -0800212}
213
214static void* create_internal(int session_id,
Song Zhaoc03ba122020-12-23 21:54:02 -0800215 enum sync_mode mode,
Song Zhaoea5a0412021-01-18 16:40:08 -0800216 enum sync_type type,
Song Zhaoc03ba122020-12-23 21:54:02 -0800217 int start_thres,
Song Zhaoea5a0412021-01-18 16:40:08 -0800218 bool attach)
Song Zhaoc03ba122020-12-23 21:54:02 -0800219{
220 struct av_sync_session *avsync = NULL;
Song Zhaoea5a0412021-01-18 16:40:08 -0800221 char dev_name[20];
Song Zhao2f6744b2021-11-03 21:23:50 -0700222 int retry = 10;
Song Zhaoc03ba122020-12-23 21:54:02 -0800223
Song Zhao95bd0922021-09-21 14:07:46 -0700224 log_info("[%d] mode %d type %d", session_id, mode, type);
Song Zhaoc03ba122020-12-23 21:54:02 -0800225 avsync = (struct av_sync_session *)calloc(1, sizeof(*avsync));
226 if (!avsync) {
227 log_error("OOM");
228 return NULL;
229 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800230
Song Zhao95bd0922021-09-21 14:07:46 -0700231 if (type == AV_SYNC_TYPE_VIDEO &&
232 mode == AV_SYNC_MODE_VIDEO_MONO) {
233 if (session_id < AV_SYNC_SESSION_V_MONO) {
234 log_error("wrong session id %d", session_id);
235 goto err;
236 }
237 avsync->type = type;
238 avsync->mode = mode;
239 avsync->fd = -1;
240 avsync->session_id = session_id;
241 log_info("[%d]init", avsync->session_id);
242 return avsync;
243 }
244
Song Zhaoea5a0412021-01-18 16:40:08 -0800245 if (type == AV_SYNC_TYPE_VIDEO) {
246 avsync->pattern_detector = create_pattern_detector();
247 if (!avsync->pattern_detector) {
248 log_error("pd create fail");
249 goto err;
250 }
251
252 if (!start_thres)
253 avsync->start_thres = DEFAULT_START_THRESHOLD;
254 else {
255 if (start_thres > 5) {
256 log_error("start_thres too big: %d", start_thres);
257 goto err2;
258 }
259 avsync->start_thres = start_thres;
260 }
261 avsync->phase_set = false;
262 avsync->first_frame_toggled = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800263 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800264
265 avsync->type = type;
Song Zhaoc03ba122020-12-23 21:54:02 -0800266 avsync->state = AV_SYNC_STAT_INIT;
Song Zhaoc03ba122020-12-23 21:54:02 -0800267 avsync->paused = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800268 avsync->session_id = session_id;
Song Zhaoea5a0412021-01-18 16:40:08 -0800269 avsync->backup_mode = mode;
Song Zhaoc03ba122020-12-23 21:54:02 -0800270 avsync->last_frame = NULL;
Song Zhaoea5a0412021-01-18 16:40:08 -0800271 avsync->session_started = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800272 avsync->speed = 1.0f;
273 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
Song Zhao409739b2021-05-12 22:21:40 -0700274 avsync->vsync_interval = -1;
275 avsync->last_disc_pts = -1;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700276 avsync->last_log_syst = -1;
277 avsync->last_pts = -1;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700278 avsync->last_q_pts = -1;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700279 avsync->last_wall = -1;
280 avsync->fps_interval = -1;
281 avsync->last_r_syst = -1;
bo.xiao5821fc72021-07-11 22:47:00 -0400282 avsync->timeout = -1;
283
Song Zhaof46932e2021-05-21 01:51:45 -0700284 if (msync_session_get_disc_thres(session_id,
285 &avsync->disc_thres_min, &avsync->disc_thres_max)) {
286 log_error("fail to get disc thres", dev_name, errno);
287 avsync->disc_thres_min = AV_DISC_THRES_MIN;
288 avsync->disc_thres_max = AV_DISC_THRES_MAX;
289 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800290
291 pthread_mutex_init(&avsync->lock, NULL);
Song Zhao95bd0922021-09-21 14:07:46 -0700292 log_info("[%d] start_thres %d disc_thres %u/%u",
293 start_thres, avsync->disc_thres_min, avsync->disc_thres_max);
Song Zhaoea5a0412021-01-18 16:40:08 -0800294
295 snprintf(dev_name, sizeof(dev_name), "/dev/%s%d", SESSION_DEV, session_id);
Song Zhao2f6744b2021-11-03 21:23:50 -0700296 while (retry) {
297 /* wait for sysfs to update */
298 avsync->fd = open(dev_name, O_RDONLY | O_CLOEXEC);
299 if (avsync->fd > 0)
300 break;
301
302 retry--;
303 if (!retry) {
304 log_error("open %s errno %d", dev_name, errno);
305 goto err2;
306 }
307 usleep(20000);
Song Zhaoea5a0412021-01-18 16:40:08 -0800308 }
309
wei.dubcc2ed22021-05-19 07:16:10 -0400310 if (avsync->type == AV_SYNC_TYPE_PCR) {
311 if (pcr_monitor_init(&avsync->pcr_monitor)) {
312 log_error("pcr monitor init");
Song Zhao9cd27a52021-07-26 15:27:38 +0000313 goto err3;
wei.dubcc2ed22021-05-19 07:16:10 -0400314 }
315 }
316
Song Zhaoea5a0412021-01-18 16:40:08 -0800317 if (!attach) {
318 msync_session_set_mode(avsync->fd, mode);
319 avsync->mode = mode;
320 } else {
321 avsync->attached = true;
322 if (msync_session_get_mode(avsync->fd, &avsync->mode)) {
323 log_error("get mode");
Song Zhao9cd27a52021-07-26 15:27:38 +0000324 goto err4;
Song Zhaoea5a0412021-01-18 16:40:08 -0800325 }
326 avsync->backup_mode = avsync->mode;
bo.xiao5821fc72021-07-11 22:47:00 -0400327 if (msync_session_get_start_policy(avsync->fd, &avsync->start_policy, &avsync->timeout)) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800328 log_error("get policy");
Song Zhao9cd27a52021-07-26 15:27:38 +0000329 goto err4;
Song Zhaoea5a0412021-01-18 16:40:08 -0800330 }
yongchun.li107a6162021-05-05 02:38:57 -0700331 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700332 NULL, NULL, NULL, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -0700333 log_error("get state");
Song Zhao9cd27a52021-07-26 15:27:38 +0000334 goto err4;
yongchun.li107a6162021-05-05 02:38:57 -0700335 }
336 if (avsync->in_audio_switch) {
337 log_info("audio_switch_state reseted the audio");
338 avsync->audio_switch_state = AUDIO_SWITCH_STAT_RESET;
339 }
340
Song Zhaoea5a0412021-01-18 16:40:08 -0800341 log_info("[%d]retrieve sync mode %d policy %d",
342 session_id, avsync->mode, avsync->start_policy);
343 }
344
Song Zhao67c937b2021-10-01 11:21:32 -0700345 /* debug log level */
346 {
347 const char *env= getenv( "AML_AVSYNC_DEBUG_LEVEL");
348 if ( env ) {
349 log_set_level(atoi(env));
350 }
351 }
352
Song Zhaoc03ba122020-12-23 21:54:02 -0800353 return avsync;
Song Zhao9cd27a52021-07-26 15:27:38 +0000354err4:
wei.dubcc2ed22021-05-19 07:16:10 -0400355 if (avsync->pcr_monitor)
356 pcr_monitor_destroy(avsync->pcr_monitor);
Song Zhao9cd27a52021-07-26 15:27:38 +0000357err3:
358 close(avsync->fd);
Song Zhaoea5a0412021-01-18 16:40:08 -0800359err2:
360 destroy_pattern_detector(avsync->pattern_detector);
361err:
362 free(avsync);
363 return NULL;
364}
365
366void* av_sync_create(int session_id,
367 enum sync_mode mode,
368 enum sync_type type,
369 int start_thres)
370{
371 return create_internal(session_id, mode,
372 type, start_thres, false);
373}
374
375void* av_sync_attach(int session_id, enum sync_type type)
376{
Song Zhao95bd0922021-09-21 14:07:46 -0700377 if (type == AV_SYNC_TYPE_VIDEO)
378 return NULL;
Song Zhaoea5a0412021-01-18 16:40:08 -0800379 return create_internal(session_id, AV_SYNC_MODE_MAX,
380 type, 0, true);
381}
382
383int av_sync_video_config(void *sync, struct video_config* config)
384{
385 struct av_sync_session *avsync = (struct av_sync_session *)sync;
386
387 if (!avsync || !config)
388 return -1;
389
390 if (config->delay != 1 && config->delay != 2) {
391 log_error("invalid delay: %d\n", config->delay);
392 return -1;
393 }
394
395 avsync->delay = config->delay;
396
397 log_info("[%d] delay: %d",
398 avsync->session_id, config->delay);
399 return 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800400}
401
402static int internal_stop(struct av_sync_session *avsync)
403{
404 int ret = 0;
405 struct vframe *frame;
406
407 pthread_mutex_lock(&avsync->lock);
Song Zhaoc03ba122020-12-23 21:54:02 -0800408 while (!dqueue_item(avsync->frame_q, (void **)&frame)) {
409 frame->free(frame);
410 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800411 avsync->state = AV_SYNC_STAT_INIT;
Song Zhaoc03ba122020-12-23 21:54:02 -0800412 pthread_mutex_unlock(&avsync->lock);
413 return ret;
414}
415
416/* destroy and detach from kernel session */
417void av_sync_destroy(void *sync)
418{
419 struct av_sync_session *avsync = (struct av_sync_session *)sync;
420
421 if (!avsync)
422 return;
423
Song Zhao95bd0922021-09-21 14:07:46 -0700424 if (avsync->type == AV_SYNC_TYPE_VIDEO &&
425 avsync->mode == AV_SYNC_MODE_VIDEO_MONO) {
426 log_info("[%d]done", avsync->session_id);
427 internal_stop(avsync);
428 destroy_q(avsync->frame_q);
429 free(avsync);
430 return;
431 }
Song Zhaob5458b32021-11-12 15:58:47 -0800432 log_info("[%d]begin type %d", avsync->session_id, avsync->type);
Song Zhaoea5a0412021-01-18 16:40:08 -0800433 if (avsync->state != AV_SYNC_STAT_INIT) {
434 if (avsync->type == AV_SYNC_TYPE_VIDEO)
435 internal_stop(avsync);
Song Zhaoc03ba122020-12-23 21:54:02 -0800436
Song Zhaoea5a0412021-01-18 16:40:08 -0800437 avsync->quit_poll = true;
438 if (avsync->poll_thread) {
439 pthread_join(avsync->poll_thread, NULL);
440 avsync->poll_thread = 0;
441 }
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700442 if (avsync->type == AV_SYNC_TYPE_AUDIO)
443 trigger_audio_start_cb(avsync, AV_SYNC_ASCB_STOP);
Song Zhaoaf368d52021-02-17 17:53:45 -0800444 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800445
Song Zhaoea5a0412021-01-18 16:40:08 -0800446 if (avsync->session_started) {
447 if (avsync->type == AV_SYNC_TYPE_VIDEO)
448 msync_session_set_video_stop(avsync->fd);
449 else
450 msync_session_set_audio_stop(avsync->fd);
451 }
wei.dubcc2ed22021-05-19 07:16:10 -0400452
453 if(avsync->pcr_monitor)
454 pcr_monitor_destroy(avsync->pcr_monitor);
455
Song Zhaoea5a0412021-01-18 16:40:08 -0800456 close(avsync->fd);
Song Zhaoc03ba122020-12-23 21:54:02 -0800457 pthread_mutex_destroy(&avsync->lock);
Song Zhaoea5a0412021-01-18 16:40:08 -0800458 if (avsync->type == AV_SYNC_TYPE_VIDEO) {
459 destroy_q(avsync->frame_q);
460 destroy_pattern_detector(avsync->pattern_detector);
461 }
Song Zhaob5458b32021-11-12 15:58:47 -0800462 log_info("[%d]done type %d", avsync->session_id, avsync->type);
Song Zhaoc03ba122020-12-23 21:54:02 -0800463 free(avsync);
Song Zhaoea5a0412021-01-18 16:40:08 -0800464}
465
bo.xiao5821fc72021-07-11 22:47:00 -0400466int avs_sync_set_start_policy(void *sync, struct start_policy* st_policy)
Song Zhaoea5a0412021-01-18 16:40:08 -0800467{
468 struct av_sync_session *avsync = (struct av_sync_session *)sync;
469
470 if (!avsync || !avsync->fd)
471 return -1;
472
bo.xiao5821fc72021-07-11 22:47:00 -0400473 log_info("[%d]policy %u --> %u, timeout %d --> %d", avsync->start_policy, st_policy->policy, avsync->timeout, st_policy->timeout);
474 avsync->start_policy = st_policy->policy;
475 avsync->timeout = st_policy->timeout;
Song Zhaoea5a0412021-01-18 16:40:08 -0800476 /* v_peek will be handled by libamlavsync */
bo.xiao5821fc72021-07-11 22:47:00 -0400477 if (st_policy->policy != AV_SYNC_START_NONE &&
478 st_policy->policy != AV_SYNC_START_V_PEEK)
479 return msync_session_set_start_policy(avsync->fd, st_policy->policy, st_policy->timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -0800480
481 return 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800482}
483
484int av_sync_pause(void *sync, bool pause)
485{
486 struct av_sync_session *avsync = (struct av_sync_session *)sync;
yongchun.li107a6162021-05-05 02:38:57 -0700487 bool v_active, a_active, v_timeout;
Song Zhaoea5a0412021-01-18 16:40:08 -0800488 int rc;
Song Zhaoc03ba122020-12-23 21:54:02 -0800489
Song Zhaob5458b32021-11-12 15:58:47 -0800490 if (!avsync) {
491 log_error("invalid handle");
Song Zhaoc03ba122020-12-23 21:54:02 -0800492 return -1;
Song Zhaob5458b32021-11-12 15:58:47 -0800493 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800494
Song Zhaob5458b32021-11-12 15:58:47 -0800495 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER) {
496 log_warn("ignore pause in pcr master mode");
Song Zhaoea5a0412021-01-18 16:40:08 -0800497 return -1;
Song Zhaob5458b32021-11-12 15:58:47 -0800498 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800499
yongchun.li107a6162021-05-05 02:38:57 -0700500 rc = msync_session_get_stat(avsync->fd, &avsync->active_mode,
501 &v_active, &a_active, &v_timeout,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700502 &avsync->in_audio_switch, SRC_A);
yongchun.li107a6162021-05-05 02:38:57 -0700503
yongchun.li5f52fb02021-06-04 18:13:05 -0700504 /* ignore only when video try to pause when audio is acive, on which
505 the control of the STC will be relays.
506 When resume,it can do always as it is possible that video just
507 paused earlier without audio yet,then audio added later before resume.
508 We shall not igore that otherwise it could cause video freeze. */
509 if (avsync->mode == AV_SYNC_MODE_AMASTER &&
510 avsync->type == AV_SYNC_TYPE_VIDEO &&
511 a_active &&
512 !avsync->in_audio_switch) {
513 if (!pause) {
514 log_info("[%d] clear video pause when audio active",
515 avsync->session_id);
516 avsync->paused = pause;
517 } else {
518 log_info("[%d] ignore the pause from video when audio active",
519 avsync->session_id);
520 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800521 return 0;
yongchun.li5f52fb02021-06-04 18:13:05 -0700522 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800523
yongchun.li107a6162021-05-05 02:38:57 -0700524 if (avsync->in_audio_switch && avsync->type == AV_SYNC_TYPE_AUDIO) {
525 log_info("[%d] ignore the pause from audio", avsync->session_id);
526 avsync->audio_switch_state = AUDIO_SWITCH_STAT_RESET;
527 return 0;
528 }
529
Song Zhaoea5a0412021-01-18 16:40:08 -0800530 rc = msync_session_set_pause(avsync->fd, pause);
Song Zhaoc03ba122020-12-23 21:54:02 -0800531 avsync->paused = pause;
Song Zhaoea5a0412021-01-18 16:40:08 -0800532 log_info("[%d]paused:%d type:%d rc %d",
533 avsync->session_id, pause, avsync->type, rc);
Song Zhaoc03ba122020-12-23 21:54:02 -0800534
Song Zhaoea5a0412021-01-18 16:40:08 -0800535 return rc;
Song Zhaoc03ba122020-12-23 21:54:02 -0800536}
537
538int av_sync_push_frame(void *sync , struct vframe *frame)
539{
540 int ret;
Song Zhaoee6a1512021-09-08 11:28:57 -0700541 struct vframe *prev = NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800542 struct av_sync_session *avsync = (struct av_sync_session *)sync;
543
544 if (!avsync)
545 return -1;
546
Song Zhao95bd0922021-09-21 14:07:46 -0700547 if (avsync->type == AV_SYNC_TYPE_VIDEO &&
548 avsync->mode == AV_SYNC_MODE_VIDEO_MONO)
549 return video_mono_push_frame(avsync, frame);
550
Song Zhaoea5a0412021-01-18 16:40:08 -0800551 if (!avsync->frame_q) {
552 /* policy should be final now */
bo.xiao5821fc72021-07-11 22:47:00 -0400553 if (msync_session_get_start_policy(avsync->fd, &avsync->start_policy, &avsync->timeout)) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800554 log_error("[%d]get policy", avsync->session_id);
555 return -1;
556 }
557
558 avsync->frame_q = create_q(MAX_FRAME_NUM);
559 if (!avsync->frame_q) {
560 log_error("[%d]create queue fail", avsync->session_id);
yongchun.li0ee6e372021-08-20 04:26:04 -0700561
Song Zhaoea5a0412021-01-18 16:40:08 -0800562 return -1;
563 }
564
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700565 /* for debugging */
566 {
Song Zhaoea5a0412021-01-18 16:40:08 -0800567 int ret;
568
569 ret = pthread_create(&avsync->poll_thread, NULL, poll_thread, avsync);
570 if (ret) {
571 log_error("[%d]create poll thread errno %d", avsync->session_id, errno);
572 destroy_q(avsync->frame_q);
573 return -1;
574 }
575 }
576 }
577
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700578 if (avsync->last_q_pts != -1) {
579 if (avsync->last_q_pts == frame->pts && avsync->mode == AV_SYNC_MODE_AMASTER) {
580 /* TODO: wrong, should remove from back of queue */
Song Zhaoc03ba122020-12-23 21:54:02 -0800581 dqueue_item(avsync->frame_q, (void **)&prev);
Song Zhaoee6a1512021-09-08 11:28:57 -0700582 if (prev) {
583 prev->free(prev);
584 log_info ("[%d]drop frame with same pts %u", avsync->session_id, frame->pts);
585 }
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700586 } else if (avsync->fps_cnt < 100) {
587 int32_t interval = frame->pts - avsync->last_q_pts;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700588
589 if (interval > 0 && interval <= 4500) {
590 if (avsync->fps_interval_acc == -1) {
591 avsync->fps_interval_acc = interval;
592 avsync->fps_cnt = 1;
593 } else {
594 avsync->fps_interval_acc += interval;
595 avsync->fps_cnt++;
596 avsync->fps_interval = avsync->fps_interval_acc / avsync->fps_cnt;
597 if (avsync->fps_cnt == 100)
598 log_info("[%d] fps_interval = %d", avsync->session_id, avsync->fps_interval);
599 }
600 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800601 }
602 }
603
Song Zhao065800e2021-05-26 15:56:06 -0700604 if (frame->duration == -1)
605 frame->duration = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800606 frame->hold_period = 0;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700607 avsync->last_q_pts = frame->pts;
Song Zhaoc03ba122020-12-23 21:54:02 -0800608 ret = queue_item(avsync->frame_q, frame);
609 if (avsync->state == AV_SYNC_STAT_INIT &&
610 queue_size(avsync->frame_q) >= avsync->start_thres) {
611 avsync->state = AV_SYNC_STAT_RUNNING;
Song Zhaoea5a0412021-01-18 16:40:08 -0800612 log_info("[%d]state: init --> running", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800613 }
614
615 if (ret)
Song Zhaoe1b65602022-01-06 08:03:46 -0800616 log_error("queue fail:%d", ret);
bo.xiao1f94b352021-08-02 03:53:47 -0400617 log_debug("[%d]push %u, QNum=%d", avsync->session_id, frame->pts, queue_size(avsync->frame_q));
Song Zhaoc03ba122020-12-23 21:54:02 -0800618 return ret;
Song Zhaoc03ba122020-12-23 21:54:02 -0800619}
620
621struct vframe *av_sync_pop_frame(void *sync)
622{
Song Zhaoea5a0412021-01-18 16:40:08 -0800623 struct vframe *frame = NULL, *enter_last_frame = NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800624 struct av_sync_session *avsync = (struct av_sync_session *)sync;
625 int toggle_cnt = 0;
626 uint32_t systime;
Song Zhao468fd652021-01-15 22:13:04 -0800627 bool pause_pts_reached = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800628 uint32_t interval;
Song Zhaoc03ba122020-12-23 21:54:02 -0800629
Song Zhao95bd0922021-09-21 14:07:46 -0700630 if (avsync->type == AV_SYNC_TYPE_VIDEO &&
631 avsync->mode == AV_SYNC_MODE_VIDEO_MONO)
632 return video_mono_pop_frame(avsync);
633
Song Zhaoc03ba122020-12-23 21:54:02 -0800634 pthread_mutex_lock(&avsync->lock);
635 if (avsync->state == AV_SYNC_STAT_INIT) {
Song Zhao2f6744b2021-11-03 21:23:50 -0700636 log_debug("[%d]in state INIT", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800637 goto exit;
638 }
639
Song Zhaoea5a0412021-01-18 16:40:08 -0800640 if (!avsync->session_started) {
Song Zhao35a82df2021-04-15 10:58:49 -0700641 uint32_t pts;
642
Song Zhaoc03ba122020-12-23 21:54:02 -0800643 if (peek_item(avsync->frame_q, (void **)&frame, 0) || !frame) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800644 log_info("[%d]empty q", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800645 goto exit;
646 }
Song Zhao35a82df2021-04-15 10:58:49 -0700647 msync_session_get_wall(avsync->fd, &systime, &interval);
648 pts = frame->pts - avsync->delay * interval;
649 msync_session_set_video_start(avsync->fd, pts);
Song Zhaoea5a0412021-01-18 16:40:08 -0800650 avsync->session_started = true;
Song Zhao35a82df2021-04-15 10:58:49 -0700651 log_info("[%d]video start %u", avsync->session_id, pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800652 }
653
Song Zhaoea5a0412021-01-18 16:40:08 -0800654 if (avsync->start_policy == AV_SYNC_START_ALIGN &&
Song Zhaod4109b62021-04-30 08:47:17 -0700655 !avsync->first_frame_toggled &&
656 !msync_clock_started(avsync->fd)) {
657 pthread_mutex_unlock(&avsync->lock);
Song Zhaoea5a0412021-01-18 16:40:08 -0800658 log_trace("[%d]clock not started", avsync->session_id);
659 return NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800660 }
661
Song Zhaoea5a0412021-01-18 16:40:08 -0800662 enter_last_frame = avsync->last_frame;
663 msync_session_get_wall(avsync->fd, &systime, &interval);
664
665 /* handle refresh rate change */
666 if (avsync->vsync_interval == AV_SYNC_INVALID_PAUSE_PTS ||
667 avsync->vsync_interval != interval) {
668 log_info("[%d]vsync interval update %d --> %u",
669 avsync->session_id, avsync->vsync_interval, interval);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700670 if (avsync->fps_interval == -1)
671 avsync->fps_interval = interval;
Song Zhaoea5a0412021-01-18 16:40:08 -0800672 avsync->vsync_interval = interval;
673 avsync->phase_set = false;
Song Zhaode5f73b2021-07-23 22:38:07 -0700674 avsync->phase = 0;
Song Zhaoea5a0412021-01-18 16:40:08 -0800675 reset_pattern(avsync->pattern_detector);
676 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800677 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
678 struct vframe *next_frame = NULL;
679
680 peek_item(avsync->frame_q, (void **)&next_frame, 1);
681 if (next_frame)
Song Zhaof46932e2021-05-21 01:51:45 -0700682 log_debug("[%d]cur_f %u next_f %u size %d",
683 avsync->session_id, frame->pts, next_frame->pts, queue_size(avsync->frame_q));
Song Zhaoea5a0412021-01-18 16:40:08 -0800684 if (frame_expire(avsync, systime, interval,
685 frame, next_frame, toggle_cnt)) {
686 log_debug("[%d]cur_f %u expire", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800687 toggle_cnt++;
688
Song Zhao35a82df2021-04-15 10:58:49 -0700689 if (pattern_detect(avsync,
Song Zhaoc03ba122020-12-23 21:54:02 -0800690 (avsync->last_frame?avsync->last_frame->hold_period:0),
Song Zhao67c937b2021-10-01 11:21:32 -0700691 avsync->last_holding_peroid)) {
Song Zhao35a82df2021-04-15 10:58:49 -0700692 log_info("[%d] %u break the pattern", avsync->session_id, avsync->last_frame->pts);
Song Zhao67c937b2021-10-01 11:21:32 -0700693 log_info("[%d] cur frame %u sys %u", avsync->session_id, frame->pts, systime);
694 if (next_frame)
695 log_info("[%d] next frame %u", avsync->session_id, next_frame->pts);
696 }
Song Zhao35a82df2021-04-15 10:58:49 -0700697
Song Zhaoc03ba122020-12-23 21:54:02 -0800698 if (avsync->last_frame)
699 avsync->last_holding_peroid = avsync->last_frame->hold_period;
700
701 dqueue_item(avsync->frame_q, (void **)&frame);
702 if (avsync->last_frame) {
703 /* free frame that are not for display */
Song Zhaoea5a0412021-01-18 16:40:08 -0800704 if (toggle_cnt > 1) {
Song Zhao35a82df2021-04-15 10:58:49 -0700705 log_debug("[%d]free %u cur %u system/d %u/%u", avsync->session_id,
706 avsync->last_frame->pts, frame->pts, systime, systime - avsync->last_poptime);
Song Zhaoc03ba122020-12-23 21:54:02 -0800707 avsync->last_frame->free(avsync->last_frame);
Song Zhaoea5a0412021-01-18 16:40:08 -0800708 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800709 } else {
710 avsync->first_frame_toggled = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800711 log_info("[%d]first frame %u", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800712 }
713 avsync->last_frame = frame;
Song Zhao5d2b4772021-01-18 16:40:08 -0800714 avsync->last_pts = frame->pts;
Song Zhaoc03ba122020-12-23 21:54:02 -0800715 } else
716 break;
717 }
718
719 /* pause pts */
720 if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS && avsync->last_frame) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800721 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
Song Zhao468fd652021-01-15 22:13:04 -0800722 pause_pts_reached = true;
Song Zhaoc03ba122020-12-23 21:54:02 -0800723 else
Song Zhao468fd652021-01-15 22:13:04 -0800724 pause_pts_reached = (int)(avsync->last_frame->pts - avsync->pause_pts) >= 0;
725 } else if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS) {
726 if (!peek_item(avsync->frame_q, (void **)&frame, 0))
727 pause_pts_reached = (int)(frame->pts - avsync->pause_pts) >= 0;
728 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800729
Song Zhao468fd652021-01-15 22:13:04 -0800730 if (pause_pts_reached) {
731 if (avsync->pause_pts_cb)
732 avsync->pause_pts_cb(avsync->pause_pts,
Song Zhaoc03ba122020-12-23 21:54:02 -0800733 avsync->pause_cb_priv);
734
Song Zhao468fd652021-01-15 22:13:04 -0800735 /* stay in paused until av_sync_pause(false) */
736 avsync->paused = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800737 log_info ("[%d]reach pause pts: %u",
Song Zhaob5458b32021-11-12 15:58:47 -0800738 avsync->session_id, avsync->pause_pts);
Song Zhaoad7c8232021-12-14 11:46:48 -0800739 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
Song Zhaoc03ba122020-12-23 21:54:02 -0800740 }
741
742exit:
743 pthread_mutex_unlock(&avsync->lock);
744 if (avsync->last_frame) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800745 if (enter_last_frame != avsync->last_frame)
746 log_debug("[%d]pop %u", avsync->session_id, avsync->last_frame->pts);
bo.xiao1f94b352021-08-02 03:53:47 -0400747 log_trace("[%d]pop=%u, stc=%u, QNum=%d", avsync->session_id, avsync->last_frame->pts, systime, queue_size(avsync->frame_q));
Song Zhao065800e2021-05-26 15:56:06 -0700748 /* don't update vpts for out_lier */
749 if (avsync->last_frame->duration != -1)
750 msync_session_update_vpts(avsync->fd, systime,
751 avsync->last_frame->pts, interval * avsync->delay);
Song Zhaoc03ba122020-12-23 21:54:02 -0800752 } else
Song Zhaoea5a0412021-01-18 16:40:08 -0800753 if (enter_last_frame != avsync->last_frame)
754 log_debug("[%d]pop (nil)", avsync->session_id);
755
Song Zhao35a82df2021-04-15 10:58:49 -0700756 avsync->last_poptime = systime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800757 if (avsync->last_frame)
758 avsync->last_frame->hold_period++;
759 return avsync->last_frame;
760}
761
Song Zhaoc03ba122020-12-23 21:54:02 -0800762static inline uint32_t abs_diff(uint32_t a, uint32_t b)
763{
Song Zhaoea5a0412021-01-18 16:40:08 -0800764 return (int)(a - b) > 0 ? a - b : b - a;
Song Zhaoc03ba122020-12-23 21:54:02 -0800765}
766
yongchun.li0ee6e372021-08-20 04:26:04 -0700767static uint64_t time_diff (struct timespec *b, struct timespec *a)
Song Zhaoc03ba122020-12-23 21:54:02 -0800768{
yongchun.li0ee6e372021-08-20 04:26:04 -0700769 return (b->tv_sec - a->tv_sec)*1000000 + (b->tv_nsec/1000 - a->tv_nsec/1000);
Song Zhaoc03ba122020-12-23 21:54:02 -0800770}
771
Song Zhaoc03ba122020-12-23 21:54:02 -0800772static bool frame_expire(struct av_sync_session* avsync,
773 uint32_t systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800774 uint32_t interval,
Song Zhaoc03ba122020-12-23 21:54:02 -0800775 struct vframe * frame,
776 struct vframe * next_frame,
777 int toggle_cnt)
778{
779 uint32_t fpts = frame->pts;
780 bool expire = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800781 uint32_t pts_correction = avsync->delay * interval;
Song Zhaoc03ba122020-12-23 21:54:02 -0800782
783 if (avsync->paused && avsync->pause_pts == AV_SYNC_INVALID_PAUSE_PTS)
784 return false;
785
786 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
787 return true;
788
Song Zhaoad7c8232021-12-14 11:46:48 -0800789 if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS &&
790 avsync->pause_pts == frame->pts)
791 return true;
792
Song Zhao08fa16b2021-12-08 14:30:17 -0800793 if (systime == AV_SYNC_INVALID_PTS &&
794 avsync->mode == AV_SYNC_MODE_AMASTER)
795 return false;
796
fei.deng63e43e12021-09-23 19:44:01 +0800797 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
798 avsync->mode == AV_SYNC_MODE_VMASTER) {
799 /* We need to ensure that the video outputs smoothly,
800 so output video frame by frame hold_period */
801 if ((abs_diff(systime, fpts) > AV_PATTERN_RESET_THRES) &&
802 avsync->last_frame &&
803 (avsync->last_frame->hold_period >= (avsync->fps_interval/interval))) {
804 log_debug("[%d]vmaster/freerun systime:%u --> fpts:%u,last hold_period:%d",
805 avsync->session_id, systime, fpts,avsync->last_frame->hold_period);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700806 return true;
807 }
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700808 }
809
Song Zhaoc03ba122020-12-23 21:54:02 -0800810 if (!fpts) {
811 if (avsync->last_frame) {
812 /* try to accumulate duration as PTS */
813 fpts = avsync->vpts + avsync->last_frame->duration;
814 } else {
815 fpts = avsync->vpts;
816 }
817 }
818 systime += pts_correction;
819
820 /* phase adjustment */
821 if (avsync->phase_set)
822 systime += avsync->phase;
823
yongchun.lia50b1e92021-08-07 01:11:54 +0000824 log_trace("[%d]systime:%u phase:%d correct:%u fpts:%u",
Song Zhaoea5a0412021-01-18 16:40:08 -0800825 avsync->session_id, systime,
yongchun.lia50b1e92021-08-07 01:11:54 +0000826 avsync->phase_set? (int)avsync->phase:0, pts_correction, fpts);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700827 if (abs_diff(systime, fpts) > avsync->disc_thres_min) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800828 /* ignore discontinity under pause */
Song Zhaoea5a0412021-01-18 16:40:08 -0800829 if (avsync->paused)
Song Zhaoc03ba122020-12-23 21:54:02 -0800830 return false;
831
Song Zhaoa2985cb2021-06-24 12:01:47 -0700832 if ((VALID_TS(avsync->last_log_syst) && avsync->last_log_syst != systime) ||
833 (VALID_TS(avsync->last_pts) && avsync->last_pts != fpts)) {
yongchun.li0ee6e372021-08-20 04:26:04 -0700834 struct timespec now;
Song Zhao5d2b4772021-01-18 16:40:08 -0800835
yongchun.li0ee6e372021-08-20 04:26:04 -0700836 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700837 avsync->last_log_syst = systime;
Song Zhao5d2b4772021-01-18 16:40:08 -0800838 avsync->last_pts = fpts;
839 if (time_diff(&now, &avsync->sync_lost_print_time) >=
840 SYNC_LOST_PRINT_THRESHOLD) {
Song Zhaof46932e2021-05-21 01:51:45 -0700841 log_warn("[%d]sync lost systime:%u fpts:%u lost:%u",
Song Zhaoea5a0412021-01-18 16:40:08 -0800842 avsync->session_id, systime, fpts, avsync->sync_lost_cnt);
Song Zhao5d2b4772021-01-18 16:40:08 -0800843 avsync->sync_lost_cnt = 0;
yongchun.li0ee6e372021-08-20 04:26:04 -0700844 clock_gettime(CLOCK_MONOTONIC_RAW, &avsync->sync_lost_print_time);
Song Zhao5d2b4772021-01-18 16:40:08 -0800845 } else
846 avsync->sync_lost_cnt++;
847 }
Song Zhaod62bb392021-04-23 12:25:49 -0700848
849 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP &&
850 LIVE_MODE(avsync->mode) &&
Song Zhaoa2985cb2021-06-24 12:01:47 -0700851 VALID_TS(avsync->last_pts) &&
Song Zhao065800e2021-05-26 15:56:06 -0700852 abs_diff(avsync->last_pts, fpts) > STREAM_DISC_THRES) {
Song Zhaod62bb392021-04-23 12:25:49 -0700853 /* outlier by stream error */
854 avsync->outlier_cnt++;
Song Zhao065800e2021-05-26 15:56:06 -0700855 frame->duration = -1;
Song Zhaod62bb392021-04-23 12:25:49 -0700856 if (avsync->outlier_cnt < OUTLIER_MAX_CNT) {
857 log_info("render outlier %u", fpts);
858 return true;
859 }
860 }
861
862 avsync->outlier_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800863 avsync->state = AV_SYNC_STAT_SYNC_LOST;
864 avsync->phase_set = false;
Song Zhaode5f73b2021-07-23 22:38:07 -0700865 avsync->phase = 0;
Song Zhaoa58c3e92021-03-09 18:52:55 -0800866 reset_pattern(avsync->pattern_detector);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700867
868 if (LIVE_MODE(avsync->mode) && avsync->last_disc_pts != fpts) {
Song Zhaod62bb392021-04-23 12:25:49 -0700869 log_info ("[%d]video disc %u --> %u",
Song Zhaoa2985cb2021-06-24 12:01:47 -0700870 avsync->session_id, systime, fpts);
Song Zhao409739b2021-05-12 22:21:40 -0700871 msync_session_set_video_dis(avsync->fd, fpts);
872 avsync->last_disc_pts = fpts;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700873 }
874
875 if ((int)(systime - fpts) > 0) {
876 if ((int)(systime - fpts) < avsync->disc_thres_max) {
877 /* catch up PCR */
Song Zhaof46932e2021-05-21 01:51:45 -0700878 return true;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700879 } else {
880 /* render according to FPS */
881 if (!VALID_TS(avsync->last_r_syst) ||
882 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
883 avsync->last_r_syst = systime;
884 return true;
885 }
886 return false;
887 }
888 } else if (LIVE_MODE(avsync->mode)) {
889 /* hold if the gap is small */
890 if ((int)(fpts - systime) < avsync->disc_thres_max) {
891 return false;
892 } else {
893 /* render according to FPS */
894 if (!VALID_TS(avsync->last_r_syst) ||
895 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
896 avsync->last_r_syst = systime;
897 return true;
898 }
899 return false;
900 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800901 }
902 }
903
Song Zhao52f55192021-05-06 10:52:21 -0700904 /* In some cases, keeping pattern will enlarge the gap */
905 if (abs_diff(systime, fpts) > AV_PATTERN_RESET_THRES &&
906 avsync->first_frame_toggled) {
907 reset_pattern(avsync->pattern_detector);
Song Zhaof46932e2021-05-21 01:51:45 -0700908 log_warn("sync pattern reset sys:%u fpts:%u",
Song Zhao52f55192021-05-06 10:52:21 -0700909 systime, fpts);
910 }
911
Song Zhaoc03ba122020-12-23 21:54:02 -0800912 expire = (int)(systime - fpts) >= 0;
913
914 /* scatter the frame in different vsync whenever possible */
915 if (expire && next_frame && next_frame->pts && toggle_cnt) {
916 /* multi frame expired in current vsync but no frame in next vsync */
Song Zhaoea5a0412021-01-18 16:40:08 -0800917 if (systime + interval < next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800918 expire = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800919 log_debug("[%d]unset expire systime:%d inter:%d next_pts:%d toggle_cnt:%d",
920 avsync->session_id, systime, interval, next_frame->pts, toggle_cnt);
Song Zhaoc03ba122020-12-23 21:54:02 -0800921 }
922 } else if (!expire && next_frame && next_frame->pts && !toggle_cnt
923 && avsync->first_frame_toggled) {
924 /* next vsync will have at least 2 frame expired */
Song Zhao35a82df2021-04-15 10:58:49 -0700925 if (systime + interval >= next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800926 expire = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800927 log_debug("[%d]set expire systime:%d inter:%d next_pts:%d",
928 avsync->session_id, systime, interval, next_frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800929 }
930 }
931
Song Zhaoa58c3e92021-03-09 18:52:55 -0800932 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP)
933 correct_pattern(avsync->pattern_detector, frame, next_frame,
934 (avsync->last_frame?avsync->last_frame->hold_period:0),
935 avsync->last_holding_peroid, systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800936 interval, &expire);
Song Zhaoc03ba122020-12-23 21:54:02 -0800937
938 if (expire) {
939 avsync->vpts = fpts;
940 /* phase adjustment */
941 if (!avsync->phase_set) {
yongchun.lia50b1e92021-08-07 01:11:54 +0000942 //always adjust to the half v-sync to give most pts tolerace and unify behavior
943 if ((int)(systime - fpts) >= 0 && (int)(fpts + interval - systime) > 0) {
944 avsync->phase = interval/2 + fpts - systime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800945 avsync->phase_set = true;
yongchun.lia50b1e92021-08-07 01:11:54 +0000946 log_info("[%d]adjust phase to %d", avsync->session_id, (int)avsync->phase);
Song Zhaoc03ba122020-12-23 21:54:02 -0800947 }
948 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800949 if (avsync->state != AV_SYNC_STAT_SYNC_SETUP)
Song Zhaoea5a0412021-01-18 16:40:08 -0800950 log_info("[%d]sync setup", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800951 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhao5d2b4772021-01-18 16:40:08 -0800952 avsync->sync_lost_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800953 }
954 return expire;
955}
956
Song Zhao35a82df2021-04-15 10:58:49 -0700957static bool pattern_detect(struct av_sync_session* avsync, int cur_period, int last_period)
Song Zhaoc03ba122020-12-23 21:54:02 -0800958{
Song Zhao35a82df2021-04-15 10:58:49 -0700959 bool ret = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800960 log_trace("[%d]cur_period: %d last_period: %d",
961 avsync->session_id, cur_period, last_period);
Song Zhao35a82df2021-04-15 10:58:49 -0700962 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P32, cur_period, last_period))
963 ret = true;
964 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P22, cur_period, last_period))
965 ret = true;
966 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P41, cur_period, last_period))
967 ret = true;
968 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P11, cur_period, last_period))
969 ret = true;
970
971 return ret;
Song Zhaoc03ba122020-12-23 21:54:02 -0800972}
973
974int av_sync_set_speed(void *sync, float speed)
975{
976 struct av_sync_session *avsync = (struct av_sync_session *)sync;
977
978 if (speed < 0.001f || speed > 100) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800979 log_error("[%d]wrong speed %f [0.0001, 100]", avsync->session_id, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -0800980 return -1;
981 }
982
Song Zhaoea5a0412021-01-18 16:40:08 -0800983 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER ||
984 avsync->mode == AV_SYNC_MODE_IPTV) {
985 log_info("[%d]ignore set speed in mode %d", avsync->session_id, avsync->mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800986 return 0;
Song Zhaoea5a0412021-01-18 16:40:08 -0800987 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800988
Song Zhaoea5a0412021-01-18 16:40:08 -0800989 avsync->speed = speed;
990
991 if (avsync->type == AV_SYNC_TYPE_AUDIO) {
992 if (speed == 1.0) {
993 avsync->mode = avsync->backup_mode;
994 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
995 } else {
996 avsync->backup_mode = avsync->mode;
997 avsync->mode = AV_SYNC_MODE_FREE_RUN;
998 log_info("[%d]audio to freerun mode", avsync->session_id);
999 }
1000 }
1001#if 0
Song Zhaoc03ba122020-12-23 21:54:02 -08001002 if (avsync->mode != AV_SYNC_MODE_VMASTER) {
1003 log_info("ignore set speed in mode %d", avsync->mode);
1004 return 0;
1005 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001006#endif
Song Zhaoc03ba122020-12-23 21:54:02 -08001007
Song Zhaoea5a0412021-01-18 16:40:08 -08001008 log_info("session[%d] set rate to %f", avsync->session_id, speed);
1009 return msync_session_set_rate(avsync->fd, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -08001010}
1011
1012int av_sync_change_mode(void *sync, enum sync_mode mode)
1013{
1014 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1015
1016 if (!avsync)
1017 return -1;
1018
Song Zhaoea5a0412021-01-18 16:40:08 -08001019 if (msync_session_set_mode(avsync->fd, mode)) {
1020 log_error("[%d]fail to set mode %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -08001021 return -1;
1022 }
Song Zhaoc03ba122020-12-23 21:54:02 -08001023 avsync->mode = mode;
Song Zhaoea5a0412021-01-18 16:40:08 -08001024 log_info("[%d]update sync mode to %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -08001025 return 0;
1026}
1027
Song Zhao01031bb2021-05-13 21:23:20 -07001028int av_sync_get_mode(void *sync, enum sync_mode *mode)
1029{
1030 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1031
1032 if (!avsync || !mode)
1033 return -1;
1034
1035 *mode = avsync->mode;
1036 return 0;
1037}
1038
Song Zhaoc03ba122020-12-23 21:54:02 -08001039int av_sync_set_pause_pts(void *sync, pts90K pts)
1040{
1041 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1042
1043 if (!avsync)
1044 return -1;
1045
1046 avsync->pause_pts = pts;
Song Zhaoea5a0412021-01-18 16:40:08 -08001047 log_info("[%d]set pause pts: %u", avsync->session_id, pts);
Song Zhaoc03ba122020-12-23 21:54:02 -08001048 return 0;
1049}
1050
1051int av_sync_set_pause_pts_cb(void *sync, pause_pts_done cb, void *priv)
1052{
1053 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1054
1055 if (!avsync)
1056 return -1;
1057
1058 avsync->pause_pts_cb = cb;
1059 avsync->pause_cb_priv = priv;
1060 return 0;
1061}
Song Zhaoea5a0412021-01-18 16:40:08 -08001062
1063static void trigger_audio_start_cb(struct av_sync_session *avsync,
1064 avs_ascb_reason reason)
1065{
1066 if (avsync) {
1067 pthread_mutex_lock(&avsync->lock);
1068 if (avsync->audio_start) {
1069 avsync->audio_start(avsync->audio_start_priv, reason);
1070 avsync->session_started = true;
1071 avsync->audio_start = NULL;
1072 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
1073 }
1074 pthread_mutex_unlock(&avsync->lock);
1075 }
1076}
1077
1078avs_start_ret av_sync_audio_start(
1079 void *sync,
1080 pts90K pts,
1081 pts90K delay,
1082 audio_start_cb cb,
1083 void *priv)
1084{
1085 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1086 uint32_t start_mode;
yongchun.li59e873d2021-07-07 11:42:38 -07001087 uint32_t systime;
Song Zhaoea5a0412021-01-18 16:40:08 -08001088 avs_start_ret ret = AV_SYNC_ASTART_ERR;
1089 bool create_poll_t = false;
1090
1091 if (!avsync)
1092 return ret;
1093
yongchun.li59e873d2021-07-07 11:42:38 -07001094 log_info("%d av_sync_audio_start pts(ms) %d delay %d ms",
1095 avsync->session_id, (int)pts/90, (int)delay/90);
Song Zhaoea5a0412021-01-18 16:40:08 -08001096
yongchun.li59e873d2021-07-07 11:42:38 -07001097 if (avsync->in_audio_switch &&
1098 avsync->audio_switch_state == AUDIO_SWITCH_STAT_AGAIN)
1099 {
1100 start_mode = AVS_START_SYNC;
1101 log_info("%d AUDIO_SWITCH_STAT_AGAIN", avsync->session_id);
1102 } else {
1103 if (msync_session_set_audio_start(avsync->fd, pts, delay, &start_mode))
1104 log_error("[%d]fail to set audio start", avsync->session_id);
1105 }
1106 if (avsync->in_audio_switch &&
1107 (avsync->audio_switch_state == AUDIO_SWITCH_STAT_RESET ||
1108 avsync->audio_switch_state == AUDIO_SWITCH_STAT_AGAIN)) {
1109 msync_session_get_wall(avsync->fd, &systime, NULL);
1110 if ((int)(systime - pts) > A_ADJ_THREDHOLD_LB &&
1111 start_mode == AVS_START_SYNC) {
1112 log_info("%d audio_switch audio need drop first.ahead %d ms",
1113 avsync->session_id, (int)(systime - pts)/90);
1114 ret = AV_SYNC_ASTART_AGAIN;
1115 avsync->audio_switch_state = AUDIO_SWITCH_STAT_AGAIN;
1116 goto exit;
1117 }
1118 else {
1119 int diff = (int)(pts - systime);
1120 log_info("%d audio_switch_state to start mode %d diff %d ms",
1121 avsync->session_id, start_mode, diff/90);
1122 avsync->audio_switch_state = AUDIO_SWITCH_STAT_START;
1123 if (diff < A_ADJ_THREDHOLD_LB) {
1124 log_info("%d orig mode %d already close enough direct start",
1125 avsync->session_id, start_mode);
1126 start_mode = AVS_START_SYNC;
1127 }
1128 }
yongchun.li107a6162021-05-05 02:38:57 -07001129 }
1130
Song Zhaoea5a0412021-01-18 16:40:08 -08001131 if (start_mode == AVS_START_SYNC) {
1132 ret = AV_SYNC_ASTART_SYNC;
1133 avsync->session_started = true;
Song Zhao065800e2021-05-26 15:56:06 -07001134 avsync->state = AV_SYNC_STAT_RUNNING;
Song Zhaod62bb392021-04-23 12:25:49 -07001135 } else if (start_mode == AVS_START_ASYNC) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001136 ret = AV_SYNC_ASTART_ASYNC;
Song Zhaod62bb392021-04-23 12:25:49 -07001137 avsync->state = AV_SYNC_STAT_RUNNING;
1138 } else if (start_mode == AVS_START_AGAIN) {
1139 ret = AV_SYNC_ASTART_AGAIN;
1140 }
1141
1142 if (ret == AV_SYNC_ASTART_AGAIN)
1143 goto exit;
Song Zhaoea5a0412021-01-18 16:40:08 -08001144
yongchun.li107a6162021-05-05 02:38:57 -07001145 if (avsync->mode == AV_SYNC_MODE_AMASTER || avsync->in_audio_switch) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001146 create_poll_t = true;
1147 if (start_mode == AVS_START_ASYNC) {
1148 if (!cb) {
1149 log_error("[%d]invalid cb", avsync->session_id);
1150 return AV_SYNC_ASTART_ERR;
1151 }
1152 avsync->audio_start = cb;
1153 avsync->audio_start_priv = priv;
1154 }
Song Zhaod62bb392021-04-23 12:25:49 -07001155 } else if (LIVE_MODE(avsync->mode))
Song Zhaoea5a0412021-01-18 16:40:08 -08001156 create_poll_t = true;
1157
Song Zhaod62bb392021-04-23 12:25:49 -07001158 if (create_poll_t && !avsync->poll_thread) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001159 int ret;
1160
1161 log_info("[%d]start poll thread", avsync->session_id);
1162 avsync->quit_poll = false;
1163 ret = pthread_create(&avsync->poll_thread, NULL, poll_thread, avsync);
1164 if (ret) {
1165 log_error("[%d]create poll thread errno %d", avsync->session_id, errno);
1166 return AV_SYNC_ASTART_ERR;
1167 }
1168 }
Song Zhaod62bb392021-04-23 12:25:49 -07001169 if (LIVE_MODE(avsync->mode)) {
Song Zhaod62bb392021-04-23 12:25:49 -07001170 msync_session_get_wall(avsync->fd, &systime, NULL);
1171 log_info("[%d]return %u w %u pts %u d %u",
1172 avsync->session_id, ret, systime, pts, delay);
1173 }
1174exit:
Song Zhaoea5a0412021-01-18 16:40:08 -08001175 log_info("[%d]return %u", avsync->session_id, ret);
1176 return ret;
1177}
1178
1179int av_sync_audio_render(
1180 void *sync,
1181 pts90K pts,
1182 struct audio_policy *policy)
1183{
1184 int ret = 0;
Song Zhao065800e2021-05-26 15:56:06 -07001185 bool out_lier = false;
Song Zhaoea5a0412021-01-18 16:40:08 -08001186 uint32_t systime;
1187 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1188 avs_audio_action action = AA_SYNC_AA_MAX;
1189
1190 if (!avsync || !policy)
1191 return -1;
1192
yongchun.li107a6162021-05-05 02:38:57 -07001193 msync_session_get_wall(avsync->fd, &systime, NULL);
1194
1195 log_trace("audio render pts %u, systime %u, mode %u diff ms %d",
1196 pts, systime, avsync->mode, (int)(pts-systime)/90);
1197
1198 if (avsync->in_audio_switch
1199 && avsync->audio_switch_state == AUDIO_SWITCH_STAT_START) {
1200 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_HB) {
1201 log_info("Audio pts in system range sys %u pts %u\n", systime, pts);
1202 avsync->audio_switch_state = AUDIO_SWITCH_STAT_FINISH;
1203 action = AV_SYNC_AA_RENDER;
1204 } else if ((int)(systime - pts) > 0) {
1205 log_info("[%d] audio change drop %d ms sys %u pts %u", avsync->session_id,
1206 (int)(systime - pts)/90, systime, pts);
1207 action = AV_SYNC_AA_DROP;
1208 } else {
1209 action = AV_SYNC_AA_INSERT;
1210 log_info("[%d] audio change insert %d ms sys %u pts %u", avsync->session_id,
1211 (int)(pts - systime)/90, systime, pts);
1212 }
1213 goto done;
1214 }
1215
Song Zhaoea5a0412021-01-18 16:40:08 -08001216 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
1217 avsync->mode == AV_SYNC_MODE_AMASTER) {
1218 action = AV_SYNC_AA_RENDER;
1219 goto done;
1220 }
1221
Song Zhaod62bb392021-04-23 12:25:49 -07001222 /* stopping procedure, unblock audio rendering */
1223 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER &&
1224 avsync->active_mode == AV_SYNC_MODE_FREE_RUN) {
1225 action = AV_SYNC_AA_DROP;
1226 goto done;
1227 }
1228
Song Zhao7daf3a12021-05-10 22:22:25 -07001229 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
1230 avsync->mode == AV_SYNC_MODE_AMASTER) {
1231 action = AV_SYNC_AA_RENDER;
1232 goto done;
1233 }
1234
Song Zhaod62bb392021-04-23 12:25:49 -07001235 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP &&
1236 LIVE_MODE(avsync->mode) &&
1237 abs_diff(systime, pts) > STREAM_DISC_THRES) {
1238 /* outlier by stream error */
1239 avsync->outlier_cnt++;
1240 if (avsync->outlier_cnt > OUTLIER_MAX_CNT) {
1241 /* treat as disc, just drop current frame */
1242 avsync->state = AV_SYNC_STAT_SYNC_LOST;
1243 avsync->outlier_cnt = 0;
1244 action = AV_SYNC_AA_DROP;
1245 systime = pts;
Song Zhaod62bb392021-04-23 12:25:49 -07001246 goto done;
1247 }
1248 log_info("[%d]ignore outlier %u", avsync->session_id, pts);
1249 pts = systime;
1250 action = AV_SYNC_AA_RENDER;
Song Zhao065800e2021-05-26 15:56:06 -07001251 out_lier = true;
Song Zhaod62bb392021-04-23 12:25:49 -07001252 goto done;
1253 }
1254
1255 avsync->outlier_cnt = 0;
1256 /* low bound from sync_lost to sync_setup */
1257 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_LB) {
1258 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
1259 action = AV_SYNC_AA_RENDER;
1260 goto done;
1261 }
1262
1263 /* high bound of sync_setup */
1264 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_HB &&
1265 avsync->state != AV_SYNC_STAT_SYNC_LOST) {
1266 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhaoea5a0412021-01-18 16:40:08 -08001267 action = AV_SYNC_AA_RENDER;
1268 goto done;
1269 }
1270
1271 if ((int)(systime - pts) > 0) {
Song Zhaod62bb392021-04-23 12:25:49 -07001272 avsync->state = AV_SYNC_STAT_SYNC_LOST;
Song Zhaoea5a0412021-01-18 16:40:08 -08001273 action = AV_SYNC_AA_DROP;
1274 goto done;
1275 }
1276
1277 if ((int)(systime - pts) < 0) {
Song Zhaod62bb392021-04-23 12:25:49 -07001278 avsync->state = AV_SYNC_STAT_SYNC_LOST;
Song Zhaoea5a0412021-01-18 16:40:08 -08001279 action = AV_SYNC_AA_INSERT;
1280 goto done;
1281 }
1282
1283done:
1284 policy->action = action;
1285 policy->delta = (int)(systime - pts);
1286 if (action == AV_SYNC_AA_RENDER) {
1287 avsync->apts = pts;
yongchun.li107a6162021-05-05 02:38:57 -07001288 if (!avsync->in_audio_switch) {
Song Zhao065800e2021-05-26 15:56:06 -07001289 if (!out_lier)
1290 msync_session_update_apts(avsync->fd, systime, pts, 0);
Song Zhaof46932e2021-05-21 01:51:45 -07001291 log_debug("[%d]return %d sys %u - pts %u = %d",
Song Zhao409739b2021-05-12 22:21:40 -07001292 avsync->session_id, action, systime, pts, systime - pts);
yongchun.li107a6162021-05-05 02:38:57 -07001293 } else if(avsync->audio_switch_state == AUDIO_SWITCH_STAT_FINISH) {
1294 msync_session_update_apts(avsync->fd, systime, pts, 0);
1295 log_info("[%d] audio switch done sys %u pts %u",
1296 avsync->session_id, systime, pts);
1297 msync_session_set_audio_switch(avsync->fd, false);
1298 avsync->in_audio_switch = false;
1299 avsync->audio_switch_state = AUDIO_SWITCH_STAT_INIT;
1300 } else {
1301 log_trace("[%d] in audio switch ret %d sys %u - pts %u = %d",
1302 avsync->session_id, action, systime, pts, systime - pts);
1303 }
Song Zhaoa2985cb2021-06-24 12:01:47 -07001304 avsync->audio_drop_cnt = 0;
Song Zhaoea5a0412021-01-18 16:40:08 -08001305 } else {
Song Zhaoa2985cb2021-06-24 12:01:47 -07001306 if (abs_diff(systime, pts) > avsync->disc_thres_min &&
yongchun.li085b5a42021-05-24 04:22:53 -07001307 avsync->last_disc_pts != pts &&
1308 !avsync->in_audio_switch) {
Song Zhao409739b2021-05-12 22:21:40 -07001309 log_info ("[%d]audio disc %u --> %u",
1310 avsync->session_id, systime, pts);
1311 msync_session_set_audio_dis(avsync->fd, pts);
1312 avsync->last_disc_pts = pts;
Song Zhaoa2985cb2021-06-24 12:01:47 -07001313 } else if (action == AV_SYNC_AA_DROP) {
yongchun.li0ee6e372021-08-20 04:26:04 -07001314 struct timespec now;
Song Zhaoa2985cb2021-06-24 12:01:47 -07001315
1316 /* dropping recovery */
yongchun.li0ee6e372021-08-20 04:26:04 -07001317 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
Song Zhaoa2985cb2021-06-24 12:01:47 -07001318 if (!avsync->audio_drop_cnt)
1319 avsync->audio_drop_start = now;
1320 avsync->audio_drop_cnt++;
1321 if (time_diff(&now, &avsync->audio_drop_start) > 500000) {
1322 log_info ("[%d]audio keep dropping sys %u vs a %u",
1323 avsync->session_id, systime, pts);
1324 msync_session_set_audio_dis(avsync->fd, pts);
1325 }
Song Zhao409739b2021-05-12 22:21:40 -07001326 }
Song Zhaoa2985cb2021-06-24 12:01:47 -07001327 if (action != AV_SYNC_AA_DROP)
1328 avsync->audio_drop_cnt = 0;
Song Zhaof46932e2021-05-21 01:51:45 -07001329 log_debug("[%d]return %d sys %u - pts %u = %d",
Song Zhaod62bb392021-04-23 12:25:49 -07001330 avsync->session_id, action, systime, pts, systime - pts);
Song Zhaoea5a0412021-01-18 16:40:08 -08001331 }
1332
1333 return ret;
1334}
1335
1336int av_sync_get_clock(void *sync, pts90K *pts)
1337{
1338 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1339
1340 if (!avsync || !pts)
1341 return -1;
1342 return msync_session_get_wall(avsync->fd, pts, NULL);
1343}
1344
1345static void handle_mode_change_a(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -07001346 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -08001347{
bo.xiao1f94b352021-08-02 03:53:47 -04001348 log_info("[%d]av_sync amode %d mode %d v/a/vt %d/%d/%d", avsync->session_id,
Song Zhaoe208d692021-04-19 15:38:52 -07001349 avsync->active_mode, avsync->mode, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -08001350 if (avsync->active_mode == AV_SYNC_MODE_AMASTER) {
1351 float speed;
1352 if (avsync->start_policy == AV_SYNC_START_ALIGN &&
Song Zhaoe208d692021-04-19 15:38:52 -07001353 a_active && avsync->audio_start) {
yongchun.li107a6162021-05-05 02:38:57 -07001354 if (v_active || v_timeout || avsync->in_audio_switch) {
Song Zhaoe208d692021-04-19 15:38:52 -07001355 log_info("audio start cb");
1356 trigger_audio_start_cb(avsync, AV_SYNC_ASCB_OK);
yongchun.li107a6162021-05-05 02:38:57 -07001357 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001358 }
1359
1360 if (!msync_session_get_rate(avsync->fd, &speed)) {
1361 /* speed change is triggered by asink,
1362 * attached audio HAL will handle it
1363 */
1364 if (speed != avsync->speed)
1365 log_info("[%d]new rate %f", avsync->session_id, speed);
1366 if (speed == 1.0) {
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001367 if (avsync->mode != avsync->backup_mode) {
1368 avsync->mode = avsync->backup_mode;
1369 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
1370 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001371 } else {
1372 avsync->backup_mode = avsync->mode;
1373 avsync->mode = AV_SYNC_MODE_FREE_RUN;
1374 log_info("[%d]audio to freerun mode", avsync->session_id);
1375 }
1376 avsync->speed = speed;
1377 }
Song Zhaod62bb392021-04-23 12:25:49 -07001378 } else if (avsync->active_mode == AV_SYNC_MODE_PCR_MASTER) {
1379 struct session_debug debug;
1380 if (!msync_session_get_debug_mode(avsync->fd, &debug)) {
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001381 if (debug.debug_freerun && !avsync->debug_freerun) {
Song Zhaod62bb392021-04-23 12:25:49 -07001382 avsync->backup_mode = avsync->mode;
1383 avsync->mode = AV_SYNC_MODE_FREE_RUN;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001384 avsync->debug_freerun = true;
Song Zhaod62bb392021-04-23 12:25:49 -07001385 log_warn("[%d]audio to freerun mode", avsync->session_id);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001386 } else if (!debug.debug_freerun && avsync->debug_freerun) {
Song Zhaod62bb392021-04-23 12:25:49 -07001387 avsync->mode = avsync->backup_mode;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001388 avsync->debug_freerun = false;
Song Zhaod62bb392021-04-23 12:25:49 -07001389 log_warn("[%d]audio back to mode %d",
1390 avsync->session_id, avsync->mode);
1391 }
1392 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001393 }
1394}
1395
1396static void handle_mode_change_v(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -07001397 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -08001398{
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001399 struct session_debug debug;
1400
bo.xiao1f94b352021-08-02 03:53:47 -04001401 log_info("[%d]av_sync amode mode %d %d v/a %d/%d", avsync->session_id,
Song Zhaoea5a0412021-01-18 16:40:08 -08001402 avsync->active_mode, avsync->mode, v_active, a_active);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001403 if (!msync_session_get_debug_mode(avsync->fd, &debug)) {
1404 if (debug.debug_freerun && !avsync->debug_freerun) {
1405 avsync->backup_mode = avsync->mode;
1406 avsync->mode = AV_SYNC_MODE_FREE_RUN;
1407 avsync->debug_freerun = true;
1408 log_warn("[%d]video to freerun mode", avsync->session_id);
1409 } else if (!debug.debug_freerun && avsync->debug_freerun) {
1410 avsync->mode = avsync->backup_mode;
1411 avsync->debug_freerun = false;
1412 log_warn("[%d]video back to mode %d",
1413 avsync->session_id, avsync->mode);
Song Zhaod62bb392021-04-23 12:25:49 -07001414 }
1415 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001416}
1417
1418static void * poll_thread(void * arg)
1419{
1420 int ret = 0;
1421 struct av_sync_session *avsync = (struct av_sync_session *)arg;
1422 const int fd = avsync->fd;
1423 struct pollfd pfd = {
1424 /* default blocking capture */
1425 .events = POLLIN | POLLRDNORM | POLLPRI | POLLOUT | POLLWRNORM,
1426 .fd = avsync->fd,
1427 };
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001428 enum src_flag sflag = SRC_A;
Song Zhaoea5a0412021-01-18 16:40:08 -08001429
1430 prctl (PR_SET_NAME, "avs_poll");
1431 log_info("[%d]enter", avsync->session_id);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001432
1433 if (avsync->type == AV_SYNC_TYPE_AUDIO)
1434 sflag = SRC_A;
1435 else if (avsync->type == AV_SYNC_TYPE_VIDEO)
1436 sflag = SRC_V;
1437
Song Zhaoea5a0412021-01-18 16:40:08 -08001438 while (!avsync->quit_poll) {
1439 for (;;) {
1440 ret = poll(&pfd, 1, 10);
1441 if (ret > 0)
1442 break;
1443 if (avsync->quit_poll)
1444 goto exit;
1445 if (errno == EINTR)
1446 continue;
1447 }
1448
1449 /* error handling */
1450 if (pfd.revents & POLLERR)
1451 log_error("[%d]POLLERR received", avsync->session_id);
1452
Song Zhaod62bb392021-04-23 12:25:49 -07001453 /* mode change. Non-exclusive wait so all the processes
1454 * shall be woken up
1455 */
Song Zhaoea5a0412021-01-18 16:40:08 -08001456 if (pfd.revents & POLLPRI) {
Song Zhaoe208d692021-04-19 15:38:52 -07001457 bool v_active, a_active, v_timeout;
Song Zhaoea5a0412021-01-18 16:40:08 -08001458
1459 msync_session_get_stat(fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001460 &v_active, &a_active, &v_timeout, &avsync->in_audio_switch, sflag);
Song Zhaoea5a0412021-01-18 16:40:08 -08001461
1462 if (avsync->type == AV_SYNC_TYPE_AUDIO)
Song Zhaoe208d692021-04-19 15:38:52 -07001463 handle_mode_change_a(avsync, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -08001464 else if (avsync->type == AV_SYNC_TYPE_VIDEO)
Song Zhaoe208d692021-04-19 15:38:52 -07001465 handle_mode_change_v(avsync, v_active, a_active, v_timeout);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001466 usleep(10000);
Song Zhaoea5a0412021-01-18 16:40:08 -08001467 }
1468 }
1469exit:
1470 log_info("[%d]quit", avsync->session_id);
1471 return NULL;
1472}
1473
Song Zhao623e2f12021-09-03 15:54:04 -07001474#define DEMOD_NODE "/sys/class/dtvdemod/atsc_para"
1475/* return ppm between demod and PCR clock */
1476int32_t static dmod_get_sfo_dev(struct av_sync_session *avsync)
1477{
1478 int fd = -1, ppm = 0, nread;
1479 char buf[128];
1480 uint32_t reg_v, lock;
1481 float val;
1482
1483 fd = open(DEMOD_NODE, O_RDWR);
1484 if (fd < 0) {
1485 log_warn("node not found %s", DEMOD_NODE);
1486 /* do not retry */
1487 avsync->ppm_adjusted = true;
1488 return 0;
1489 }
1490 snprintf(buf, sizeof(buf), "%d", 5);
1491 write(fd, buf, 2);
1492
1493 lseek(fd, 0, SEEK_SET);
1494
1495 nread = read(fd, buf, sizeof(buf));
1496 if (nread <= 0) {
1497 log_error("read error");
1498 goto err;
1499 }
1500 buf[nread] = 0;
1501 if (sscanf(buf, "ck=0x%x lock=%d", &reg_v, &lock) != 2) {
1502 log_error("wrong format %s", buf);
1503 goto err;
1504 }
1505 if (lock != 0x1f) {
1506 log_info("demod not locked");
1507 goto err;
1508 }
1509 if (reg_v > ((2 << 20) - 1))
1510 reg_v -= (2 << 21);
1511 val = reg_v * 10.762238f / 12 * 1000000 / (2 << 25);
1512 ppm = val;
1513 log_info("ppm from SFO %d", ppm);
1514 avsync->ppm_adjusted = true;
1515
1516err:
1517 if (fd >= 0)
1518 close(fd);
1519 return ppm;
1520}
1521
Song Zhaod62bb392021-04-23 12:25:49 -07001522int av_sync_set_pcr_clock(void *sync, pts90K pts, uint64_t mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -08001523{
1524 struct av_sync_session *avsync = (struct av_sync_session *)sync;
wei.dubcc2ed22021-05-19 07:16:10 -04001525 struct pcr_info pcr;
1526 enum pcr_monitor_status status;
1527 int ppm;
Song Zhaoea5a0412021-01-18 16:40:08 -08001528 if (!avsync)
1529 return -1;
1530
1531 if (avsync->type != AV_SYNC_TYPE_PCR)
1532 return -2;
1533
Song Zhao623e2f12021-09-03 15:54:04 -07001534 /* initial estimation from Demod SFO HW */
1535 if (!avsync->ppm_adjusted) {
1536 ppm = dmod_get_sfo_dev(avsync);
1537 if (ppm != 0) {
1538 /* ppm > 0 means board clock is faster */
1539 msync_session_set_clock_dev(avsync->fd, -ppm);
1540 }
1541 }
wei.dubcc2ed22021-05-19 07:16:10 -04001542 pcr.monoclk = mono_clock / 1000;
1543 pcr.pts = (long long) pts * 1000 / 90;
1544 pcr_monitor_process(avsync->pcr_monitor, &pcr);
1545
1546 status = pcr_monitor_get_status(avsync->pcr_monitor);
1547
1548 if (status >= DEVIATION_READY) {
1549 pcr_monitor_get_deviation(avsync->pcr_monitor, &ppm);
1550 if (avsync->ppm != ppm) {
1551 avsync->ppm = ppm;
1552 log_info("[%d]ppm:%d", avsync->session_id, ppm);
1553 if (msync_session_set_clock_dev(avsync->fd, ppm))
1554 log_error("set clock dev fail");
Song Zhao623e2f12021-09-03 15:54:04 -07001555 else
1556 avsync->ppm_adjusted = true;
wei.dubcc2ed22021-05-19 07:16:10 -04001557 }
1558 }
1559
Song Zhaod62bb392021-04-23 12:25:49 -07001560 return msync_session_set_pcr(avsync->fd, pts, mono_clock);
Song Zhaoea5a0412021-01-18 16:40:08 -08001561}
1562
Song Zhaod62bb392021-04-23 12:25:49 -07001563int av_sync_get_pcr_clock(void *sync, pts90K *pts, uint64_t * mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -08001564{
1565 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1566
1567 if (!avsync)
1568 return -1;
1569
Song Zhaod62bb392021-04-23 12:25:49 -07001570 return msync_session_get_pcr(avsync->fd, pts, mono_clock);
Song Zhaoea5a0412021-01-18 16:40:08 -08001571}
1572
1573int av_sync_set_session_name(void *sync, const char *name)
1574{
1575 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1576
1577 if (!avsync)
1578 return -1;
1579
1580 return msync_session_set_name(avsync->fd, name);
1581}
yongchun.li107a6162021-05-05 02:38:57 -07001582
1583int av_sync_set_audio_switch(void *sync, bool start)
1584{
1585 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1586 bool v_active, a_active, v_timeout;
1587
1588 if (!avsync)
1589 return -1;
1590 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
1591 &v_active, &a_active,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001592 &v_timeout, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -07001593 log_error("[%d] can not get session state",
1594 avsync->session_id);
1595 return -1;
1596 }
1597 if (!v_active || !a_active) {
1598 log_error("[%d] no apply if not AV both active v %d a %d",
1599 avsync->session_id, v_active, a_active);
1600 return -1;
1601 }
1602 if (msync_session_set_audio_switch(avsync->fd, start)) {
1603 log_error("[%d]fail to set audio switch %d", avsync->session_id, start);
1604 return -1;
1605 }
1606 avsync->in_audio_switch = start;
1607 avsync->audio_switch_state = AUDIO_SWITCH_STAT_INIT;
1608 log_info("[%d]update audio switch to %d", avsync->session_id, start);
1609 return 0;
1610}
1611
1612int av_sync_get_audio_switch(void *sync, bool *start)
1613{
1614 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1615
1616 if (!avsync)
1617 return -1;
1618 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001619 NULL, NULL, NULL, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -07001620 log_error("[%d] can not audio seamless switch state",
1621 avsync->session_id);
1622 return -1;
1623 }
1624 if (start) *start = avsync->in_audio_switch;
1625 return 0;
Song Zhao7daf3a12021-05-10 22:22:25 -07001626}
Song Zhao8039f562021-05-18 18:11:25 -07001627
Song Zhao623e2f12021-09-03 15:54:04 -07001628enum clock_recovery_stat av_sync_get_clock_deviation(void *sync, int32_t *ppm)
Song Zhao8039f562021-05-18 18:11:25 -07001629{
1630 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1631
wei.dubcc2ed22021-05-19 07:16:10 -04001632 if (!avsync || !ppm)
1633 return CLK_RECOVERY_ERR;
1634 if (avsync->mode != AV_SYNC_MODE_PCR_MASTER)
Song Zhao8039f562021-05-18 18:11:25 -07001635 return CLK_RECOVERY_NOT_RUNNING;
1636
wei.dubcc2ed22021-05-19 07:16:10 -04001637 if (msync_session_get_clock_dev(avsync->fd, ppm))
1638 return CLK_RECOVERY_ERR;
1639
1640 if (*ppm == 0)
1641 return CLK_RECOVERY_ONGOING;
1642 else
1643 return CLK_RECOVERY_READY;
Song Zhao8039f562021-05-18 18:11:25 -07001644}
Song Zhao95bd0922021-09-21 14:07:46 -07001645
1646static int video_mono_push_frame(struct av_sync_session *avsync, struct vframe *frame)
1647{
1648 int ret;
1649
1650 if (!avsync->frame_q) {
1651 avsync->frame_q = create_q(MAX_FRAME_NUM);
1652 if (!avsync->frame_q) {
1653 log_error("[%d]create queue fail", avsync->session_id);
1654
1655 return -1;
1656 }
1657 }
1658
1659 ret = queue_item(avsync->frame_q, frame);
1660 if (ret)
1661 log_error("%s queue fail:%d", ret);
1662 log_debug("[%d]push %llu, QNum=%d", avsync->session_id, frame->mts, queue_size(avsync->frame_q));
1663 return ret;
1664}
1665
1666int av_sync_set_vsync_mono_time(void *sync , uint64_t msys)
1667{
1668 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1669
1670 if (!avsync)
1671 return -1;
1672 avsync->msys = msys;
1673 return 0;
1674}
1675
1676static struct vframe * video_mono_pop_frame(struct av_sync_session *avsync)
1677{
1678 struct vframe *frame = NULL, *enter_last_frame = NULL;
1679 uint64_t systime;
1680 int toggle_cnt = 0;
1681
1682 enter_last_frame = avsync->last_frame;
1683 systime = avsync->msys;
1684 log_debug("[%d]sys %llu", avsync->session_id, systime);
1685 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
1686 if (systime >= frame->mts) {
1687 log_debug("[%d]cur_f %llu expire", avsync->session_id, frame->mts);
1688 toggle_cnt++;
1689
1690 if (avsync->last_frame)
1691 avsync->last_holding_peroid = avsync->last_frame->hold_period;
1692
1693 dqueue_item(avsync->frame_q, (void **)&frame);
1694 if (avsync->last_frame) {
1695 /* free frame that are not for display */
1696 if (toggle_cnt > 1) {
1697 log_debug("[%d]free %llu cur %llu system %llu", avsync->session_id,
1698 avsync->last_frame->mts, frame->mts, systime);
1699 avsync->last_frame->free(avsync->last_frame);
1700 }
1701 } else {
1702 avsync->first_frame_toggled = true;
1703 log_info("[%d]first frame %llu", avsync->session_id, frame->mts);
1704 }
1705 avsync->last_frame = frame;
1706 } else
1707 break;
1708 }
1709
1710 if (avsync->last_frame) {
1711 if (enter_last_frame != avsync->last_frame)
1712 log_debug("[%d]pop %llu", avsync->session_id, avsync->last_frame->pts);
1713 log_trace("[%d]pop=%llu, system=%llu, diff %d(ms), QNum=%d", avsync->session_id,
1714 avsync->last_frame->mts,
1715 systime, (systime - avsync->last_frame->mts) / 1000000,
1716 queue_size(avsync->frame_q));
1717 } else
1718 if (enter_last_frame != avsync->last_frame)
1719 log_debug("[%d]pop (nil)", avsync->session_id);
1720
1721 if (avsync->last_frame)
1722 avsync->last_frame->hold_period++;
1723 return avsync->last_frame;
1724}