blob: dd8d8549ba421fd22bc636b8ad39a1aef684f7c9 [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 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)
616 log_error("%s 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;
737 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
Song Zhaoea5a0412021-01-18 16:40:08 -0800738 log_info ("[%d]reach pause pts: %u",
Song Zhaob5458b32021-11-12 15:58:47 -0800739 avsync->session_id, avsync->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 Zhao08fa16b2021-12-08 14:30:17 -0800789 if (systime == AV_SYNC_INVALID_PTS &&
790 avsync->mode == AV_SYNC_MODE_AMASTER)
791 return false;
792
fei.deng63e43e12021-09-23 19:44:01 +0800793 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
794 avsync->mode == AV_SYNC_MODE_VMASTER) {
795 /* We need to ensure that the video outputs smoothly,
796 so output video frame by frame hold_period */
797 if ((abs_diff(systime, fpts) > AV_PATTERN_RESET_THRES) &&
798 avsync->last_frame &&
799 (avsync->last_frame->hold_period >= (avsync->fps_interval/interval))) {
800 log_debug("[%d]vmaster/freerun systime:%u --> fpts:%u,last hold_period:%d",
801 avsync->session_id, systime, fpts,avsync->last_frame->hold_period);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700802 return true;
803 }
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700804 }
805
Song Zhaoc03ba122020-12-23 21:54:02 -0800806 if (!fpts) {
807 if (avsync->last_frame) {
808 /* try to accumulate duration as PTS */
809 fpts = avsync->vpts + avsync->last_frame->duration;
810 } else {
811 fpts = avsync->vpts;
812 }
813 }
814 systime += pts_correction;
815
816 /* phase adjustment */
817 if (avsync->phase_set)
818 systime += avsync->phase;
819
yongchun.lia50b1e92021-08-07 01:11:54 +0000820 log_trace("[%d]systime:%u phase:%d correct:%u fpts:%u",
Song Zhaoea5a0412021-01-18 16:40:08 -0800821 avsync->session_id, systime,
yongchun.lia50b1e92021-08-07 01:11:54 +0000822 avsync->phase_set? (int)avsync->phase:0, pts_correction, fpts);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700823 if (abs_diff(systime, fpts) > avsync->disc_thres_min) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800824 /* ignore discontinity under pause */
Song Zhaoea5a0412021-01-18 16:40:08 -0800825 if (avsync->paused)
Song Zhaoc03ba122020-12-23 21:54:02 -0800826 return false;
827
Song Zhaoa2985cb2021-06-24 12:01:47 -0700828 if ((VALID_TS(avsync->last_log_syst) && avsync->last_log_syst != systime) ||
829 (VALID_TS(avsync->last_pts) && avsync->last_pts != fpts)) {
yongchun.li0ee6e372021-08-20 04:26:04 -0700830 struct timespec now;
Song Zhao5d2b4772021-01-18 16:40:08 -0800831
yongchun.li0ee6e372021-08-20 04:26:04 -0700832 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700833 avsync->last_log_syst = systime;
Song Zhao5d2b4772021-01-18 16:40:08 -0800834 avsync->last_pts = fpts;
835 if (time_diff(&now, &avsync->sync_lost_print_time) >=
836 SYNC_LOST_PRINT_THRESHOLD) {
Song Zhaof46932e2021-05-21 01:51:45 -0700837 log_warn("[%d]sync lost systime:%u fpts:%u lost:%u",
Song Zhaoea5a0412021-01-18 16:40:08 -0800838 avsync->session_id, systime, fpts, avsync->sync_lost_cnt);
Song Zhao5d2b4772021-01-18 16:40:08 -0800839 avsync->sync_lost_cnt = 0;
yongchun.li0ee6e372021-08-20 04:26:04 -0700840 clock_gettime(CLOCK_MONOTONIC_RAW, &avsync->sync_lost_print_time);
Song Zhao5d2b4772021-01-18 16:40:08 -0800841 } else
842 avsync->sync_lost_cnt++;
843 }
Song Zhaod62bb392021-04-23 12:25:49 -0700844
845 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP &&
846 LIVE_MODE(avsync->mode) &&
Song Zhaoa2985cb2021-06-24 12:01:47 -0700847 VALID_TS(avsync->last_pts) &&
Song Zhao065800e2021-05-26 15:56:06 -0700848 abs_diff(avsync->last_pts, fpts) > STREAM_DISC_THRES) {
Song Zhaod62bb392021-04-23 12:25:49 -0700849 /* outlier by stream error */
850 avsync->outlier_cnt++;
Song Zhao065800e2021-05-26 15:56:06 -0700851 frame->duration = -1;
Song Zhaod62bb392021-04-23 12:25:49 -0700852 if (avsync->outlier_cnt < OUTLIER_MAX_CNT) {
853 log_info("render outlier %u", fpts);
854 return true;
855 }
856 }
857
858 avsync->outlier_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800859 avsync->state = AV_SYNC_STAT_SYNC_LOST;
860 avsync->phase_set = false;
Song Zhaode5f73b2021-07-23 22:38:07 -0700861 avsync->phase = 0;
Song Zhaoa58c3e92021-03-09 18:52:55 -0800862 reset_pattern(avsync->pattern_detector);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700863
864 if (LIVE_MODE(avsync->mode) && avsync->last_disc_pts != fpts) {
Song Zhaod62bb392021-04-23 12:25:49 -0700865 log_info ("[%d]video disc %u --> %u",
Song Zhaoa2985cb2021-06-24 12:01:47 -0700866 avsync->session_id, systime, fpts);
Song Zhao409739b2021-05-12 22:21:40 -0700867 msync_session_set_video_dis(avsync->fd, fpts);
868 avsync->last_disc_pts = fpts;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700869 }
870
871 if ((int)(systime - fpts) > 0) {
872 if ((int)(systime - fpts) < avsync->disc_thres_max) {
873 /* catch up PCR */
Song Zhaof46932e2021-05-21 01:51:45 -0700874 return true;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700875 } else {
876 /* render according to FPS */
877 if (!VALID_TS(avsync->last_r_syst) ||
878 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
879 avsync->last_r_syst = systime;
880 return true;
881 }
882 return false;
883 }
884 } else if (LIVE_MODE(avsync->mode)) {
885 /* hold if the gap is small */
886 if ((int)(fpts - systime) < avsync->disc_thres_max) {
887 return false;
888 } else {
889 /* render according to FPS */
890 if (!VALID_TS(avsync->last_r_syst) ||
891 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
892 avsync->last_r_syst = systime;
893 return true;
894 }
895 return false;
896 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800897 }
898 }
899
Song Zhao52f55192021-05-06 10:52:21 -0700900 /* In some cases, keeping pattern will enlarge the gap */
901 if (abs_diff(systime, fpts) > AV_PATTERN_RESET_THRES &&
902 avsync->first_frame_toggled) {
903 reset_pattern(avsync->pattern_detector);
Song Zhaof46932e2021-05-21 01:51:45 -0700904 log_warn("sync pattern reset sys:%u fpts:%u",
Song Zhao52f55192021-05-06 10:52:21 -0700905 systime, fpts);
906 }
907
Song Zhaoc03ba122020-12-23 21:54:02 -0800908 expire = (int)(systime - fpts) >= 0;
909
910 /* scatter the frame in different vsync whenever possible */
911 if (expire && next_frame && next_frame->pts && toggle_cnt) {
912 /* multi frame expired in current vsync but no frame in next vsync */
Song Zhaoea5a0412021-01-18 16:40:08 -0800913 if (systime + interval < next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800914 expire = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800915 log_debug("[%d]unset expire systime:%d inter:%d next_pts:%d toggle_cnt:%d",
916 avsync->session_id, systime, interval, next_frame->pts, toggle_cnt);
Song Zhaoc03ba122020-12-23 21:54:02 -0800917 }
918 } else if (!expire && next_frame && next_frame->pts && !toggle_cnt
919 && avsync->first_frame_toggled) {
920 /* next vsync will have at least 2 frame expired */
Song Zhao35a82df2021-04-15 10:58:49 -0700921 if (systime + interval >= next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800922 expire = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800923 log_debug("[%d]set expire systime:%d inter:%d next_pts:%d",
924 avsync->session_id, systime, interval, next_frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800925 }
926 }
927
Song Zhaoa58c3e92021-03-09 18:52:55 -0800928 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP)
929 correct_pattern(avsync->pattern_detector, frame, next_frame,
930 (avsync->last_frame?avsync->last_frame->hold_period:0),
931 avsync->last_holding_peroid, systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800932 interval, &expire);
Song Zhaoc03ba122020-12-23 21:54:02 -0800933
934 if (expire) {
935 avsync->vpts = fpts;
936 /* phase adjustment */
937 if (!avsync->phase_set) {
yongchun.lia50b1e92021-08-07 01:11:54 +0000938 //always adjust to the half v-sync to give most pts tolerace and unify behavior
939 if ((int)(systime - fpts) >= 0 && (int)(fpts + interval - systime) > 0) {
940 avsync->phase = interval/2 + fpts - systime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800941 avsync->phase_set = true;
yongchun.lia50b1e92021-08-07 01:11:54 +0000942 log_info("[%d]adjust phase to %d", avsync->session_id, (int)avsync->phase);
Song Zhaoc03ba122020-12-23 21:54:02 -0800943 }
944 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800945 if (avsync->state != AV_SYNC_STAT_SYNC_SETUP)
Song Zhaoea5a0412021-01-18 16:40:08 -0800946 log_info("[%d]sync setup", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800947 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhao5d2b4772021-01-18 16:40:08 -0800948 avsync->sync_lost_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800949 }
950 return expire;
951}
952
Song Zhao35a82df2021-04-15 10:58:49 -0700953static bool pattern_detect(struct av_sync_session* avsync, int cur_period, int last_period)
Song Zhaoc03ba122020-12-23 21:54:02 -0800954{
Song Zhao35a82df2021-04-15 10:58:49 -0700955 bool ret = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800956 log_trace("[%d]cur_period: %d last_period: %d",
957 avsync->session_id, cur_period, last_period);
Song Zhao35a82df2021-04-15 10:58:49 -0700958 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P32, cur_period, last_period))
959 ret = true;
960 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P22, cur_period, last_period))
961 ret = true;
962 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P41, cur_period, last_period))
963 ret = true;
964 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P11, cur_period, last_period))
965 ret = true;
966
967 return ret;
Song Zhaoc03ba122020-12-23 21:54:02 -0800968}
969
970int av_sync_set_speed(void *sync, float speed)
971{
972 struct av_sync_session *avsync = (struct av_sync_session *)sync;
973
974 if (speed < 0.001f || speed > 100) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800975 log_error("[%d]wrong speed %f [0.0001, 100]", avsync->session_id, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -0800976 return -1;
977 }
978
Song Zhaoea5a0412021-01-18 16:40:08 -0800979 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER ||
980 avsync->mode == AV_SYNC_MODE_IPTV) {
981 log_info("[%d]ignore set speed in mode %d", avsync->session_id, avsync->mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800982 return 0;
Song Zhaoea5a0412021-01-18 16:40:08 -0800983 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800984
Song Zhaoea5a0412021-01-18 16:40:08 -0800985 avsync->speed = speed;
986
987 if (avsync->type == AV_SYNC_TYPE_AUDIO) {
988 if (speed == 1.0) {
989 avsync->mode = avsync->backup_mode;
990 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
991 } else {
992 avsync->backup_mode = avsync->mode;
993 avsync->mode = AV_SYNC_MODE_FREE_RUN;
994 log_info("[%d]audio to freerun mode", avsync->session_id);
995 }
996 }
997#if 0
Song Zhaoc03ba122020-12-23 21:54:02 -0800998 if (avsync->mode != AV_SYNC_MODE_VMASTER) {
999 log_info("ignore set speed in mode %d", avsync->mode);
1000 return 0;
1001 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001002#endif
Song Zhaoc03ba122020-12-23 21:54:02 -08001003
Song Zhaoea5a0412021-01-18 16:40:08 -08001004 log_info("session[%d] set rate to %f", avsync->session_id, speed);
1005 return msync_session_set_rate(avsync->fd, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -08001006}
1007
1008int av_sync_change_mode(void *sync, enum sync_mode mode)
1009{
1010 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1011
1012 if (!avsync)
1013 return -1;
1014
Song Zhaoea5a0412021-01-18 16:40:08 -08001015 if (msync_session_set_mode(avsync->fd, mode)) {
1016 log_error("[%d]fail to set mode %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -08001017 return -1;
1018 }
Song Zhaoc03ba122020-12-23 21:54:02 -08001019 avsync->mode = mode;
Song Zhaoea5a0412021-01-18 16:40:08 -08001020 log_info("[%d]update sync mode to %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -08001021 return 0;
1022}
1023
Song Zhao01031bb2021-05-13 21:23:20 -07001024int av_sync_get_mode(void *sync, enum sync_mode *mode)
1025{
1026 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1027
1028 if (!avsync || !mode)
1029 return -1;
1030
1031 *mode = avsync->mode;
1032 return 0;
1033}
1034
Song Zhaoc03ba122020-12-23 21:54:02 -08001035int av_sync_set_pause_pts(void *sync, pts90K pts)
1036{
1037 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1038
1039 if (!avsync)
1040 return -1;
1041
1042 avsync->pause_pts = pts;
Song Zhaoea5a0412021-01-18 16:40:08 -08001043 log_info("[%d]set pause pts: %u", avsync->session_id, pts);
Song Zhaoc03ba122020-12-23 21:54:02 -08001044 return 0;
1045}
1046
1047int av_sync_set_pause_pts_cb(void *sync, pause_pts_done cb, void *priv)
1048{
1049 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1050
1051 if (!avsync)
1052 return -1;
1053
1054 avsync->pause_pts_cb = cb;
1055 avsync->pause_cb_priv = priv;
1056 return 0;
1057}
Song Zhaoea5a0412021-01-18 16:40:08 -08001058
1059static void trigger_audio_start_cb(struct av_sync_session *avsync,
1060 avs_ascb_reason reason)
1061{
1062 if (avsync) {
1063 pthread_mutex_lock(&avsync->lock);
1064 if (avsync->audio_start) {
1065 avsync->audio_start(avsync->audio_start_priv, reason);
1066 avsync->session_started = true;
1067 avsync->audio_start = NULL;
1068 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
1069 }
1070 pthread_mutex_unlock(&avsync->lock);
1071 }
1072}
1073
1074avs_start_ret av_sync_audio_start(
1075 void *sync,
1076 pts90K pts,
1077 pts90K delay,
1078 audio_start_cb cb,
1079 void *priv)
1080{
1081 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1082 uint32_t start_mode;
yongchun.li59e873d2021-07-07 11:42:38 -07001083 uint32_t systime;
Song Zhaoea5a0412021-01-18 16:40:08 -08001084 avs_start_ret ret = AV_SYNC_ASTART_ERR;
1085 bool create_poll_t = false;
1086
1087 if (!avsync)
1088 return ret;
1089
yongchun.li59e873d2021-07-07 11:42:38 -07001090 log_info("%d av_sync_audio_start pts(ms) %d delay %d ms",
1091 avsync->session_id, (int)pts/90, (int)delay/90);
Song Zhaoea5a0412021-01-18 16:40:08 -08001092
yongchun.li59e873d2021-07-07 11:42:38 -07001093 if (avsync->in_audio_switch &&
1094 avsync->audio_switch_state == AUDIO_SWITCH_STAT_AGAIN)
1095 {
1096 start_mode = AVS_START_SYNC;
1097 log_info("%d AUDIO_SWITCH_STAT_AGAIN", avsync->session_id);
1098 } else {
1099 if (msync_session_set_audio_start(avsync->fd, pts, delay, &start_mode))
1100 log_error("[%d]fail to set audio start", avsync->session_id);
1101 }
1102 if (avsync->in_audio_switch &&
1103 (avsync->audio_switch_state == AUDIO_SWITCH_STAT_RESET ||
1104 avsync->audio_switch_state == AUDIO_SWITCH_STAT_AGAIN)) {
1105 msync_session_get_wall(avsync->fd, &systime, NULL);
1106 if ((int)(systime - pts) > A_ADJ_THREDHOLD_LB &&
1107 start_mode == AVS_START_SYNC) {
1108 log_info("%d audio_switch audio need drop first.ahead %d ms",
1109 avsync->session_id, (int)(systime - pts)/90);
1110 ret = AV_SYNC_ASTART_AGAIN;
1111 avsync->audio_switch_state = AUDIO_SWITCH_STAT_AGAIN;
1112 goto exit;
1113 }
1114 else {
1115 int diff = (int)(pts - systime);
1116 log_info("%d audio_switch_state to start mode %d diff %d ms",
1117 avsync->session_id, start_mode, diff/90);
1118 avsync->audio_switch_state = AUDIO_SWITCH_STAT_START;
1119 if (diff < A_ADJ_THREDHOLD_LB) {
1120 log_info("%d orig mode %d already close enough direct start",
1121 avsync->session_id, start_mode);
1122 start_mode = AVS_START_SYNC;
1123 }
1124 }
yongchun.li107a6162021-05-05 02:38:57 -07001125 }
1126
Song Zhaoea5a0412021-01-18 16:40:08 -08001127 if (start_mode == AVS_START_SYNC) {
1128 ret = AV_SYNC_ASTART_SYNC;
1129 avsync->session_started = true;
Song Zhao065800e2021-05-26 15:56:06 -07001130 avsync->state = AV_SYNC_STAT_RUNNING;
Song Zhaod62bb392021-04-23 12:25:49 -07001131 } else if (start_mode == AVS_START_ASYNC) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001132 ret = AV_SYNC_ASTART_ASYNC;
Song Zhaod62bb392021-04-23 12:25:49 -07001133 avsync->state = AV_SYNC_STAT_RUNNING;
1134 } else if (start_mode == AVS_START_AGAIN) {
1135 ret = AV_SYNC_ASTART_AGAIN;
1136 }
1137
1138 if (ret == AV_SYNC_ASTART_AGAIN)
1139 goto exit;
Song Zhaoea5a0412021-01-18 16:40:08 -08001140
yongchun.li107a6162021-05-05 02:38:57 -07001141 if (avsync->mode == AV_SYNC_MODE_AMASTER || avsync->in_audio_switch) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001142 create_poll_t = true;
1143 if (start_mode == AVS_START_ASYNC) {
1144 if (!cb) {
1145 log_error("[%d]invalid cb", avsync->session_id);
1146 return AV_SYNC_ASTART_ERR;
1147 }
1148 avsync->audio_start = cb;
1149 avsync->audio_start_priv = priv;
1150 }
Song Zhaod62bb392021-04-23 12:25:49 -07001151 } else if (LIVE_MODE(avsync->mode))
Song Zhaoea5a0412021-01-18 16:40:08 -08001152 create_poll_t = true;
1153
Song Zhaod62bb392021-04-23 12:25:49 -07001154 if (create_poll_t && !avsync->poll_thread) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001155 int ret;
1156
1157 log_info("[%d]start poll thread", avsync->session_id);
1158 avsync->quit_poll = false;
1159 ret = pthread_create(&avsync->poll_thread, NULL, poll_thread, avsync);
1160 if (ret) {
1161 log_error("[%d]create poll thread errno %d", avsync->session_id, errno);
1162 return AV_SYNC_ASTART_ERR;
1163 }
1164 }
Song Zhaod62bb392021-04-23 12:25:49 -07001165 if (LIVE_MODE(avsync->mode)) {
Song Zhaod62bb392021-04-23 12:25:49 -07001166 msync_session_get_wall(avsync->fd, &systime, NULL);
1167 log_info("[%d]return %u w %u pts %u d %u",
1168 avsync->session_id, ret, systime, pts, delay);
1169 }
1170exit:
Song Zhaoea5a0412021-01-18 16:40:08 -08001171 log_info("[%d]return %u", avsync->session_id, ret);
1172 return ret;
1173}
1174
1175int av_sync_audio_render(
1176 void *sync,
1177 pts90K pts,
1178 struct audio_policy *policy)
1179{
1180 int ret = 0;
Song Zhao065800e2021-05-26 15:56:06 -07001181 bool out_lier = false;
Song Zhaoea5a0412021-01-18 16:40:08 -08001182 uint32_t systime;
1183 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1184 avs_audio_action action = AA_SYNC_AA_MAX;
1185
1186 if (!avsync || !policy)
1187 return -1;
1188
yongchun.li107a6162021-05-05 02:38:57 -07001189 msync_session_get_wall(avsync->fd, &systime, NULL);
1190
1191 log_trace("audio render pts %u, systime %u, mode %u diff ms %d",
1192 pts, systime, avsync->mode, (int)(pts-systime)/90);
1193
1194 if (avsync->in_audio_switch
1195 && avsync->audio_switch_state == AUDIO_SWITCH_STAT_START) {
1196 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_HB) {
1197 log_info("Audio pts in system range sys %u pts %u\n", systime, pts);
1198 avsync->audio_switch_state = AUDIO_SWITCH_STAT_FINISH;
1199 action = AV_SYNC_AA_RENDER;
1200 } else if ((int)(systime - pts) > 0) {
1201 log_info("[%d] audio change drop %d ms sys %u pts %u", avsync->session_id,
1202 (int)(systime - pts)/90, systime, pts);
1203 action = AV_SYNC_AA_DROP;
1204 } else {
1205 action = AV_SYNC_AA_INSERT;
1206 log_info("[%d] audio change insert %d ms sys %u pts %u", avsync->session_id,
1207 (int)(pts - systime)/90, systime, pts);
1208 }
1209 goto done;
1210 }
1211
Song Zhaoea5a0412021-01-18 16:40:08 -08001212 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
1213 avsync->mode == AV_SYNC_MODE_AMASTER) {
1214 action = AV_SYNC_AA_RENDER;
1215 goto done;
1216 }
1217
Song Zhaod62bb392021-04-23 12:25:49 -07001218 /* stopping procedure, unblock audio rendering */
1219 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER &&
1220 avsync->active_mode == AV_SYNC_MODE_FREE_RUN) {
1221 action = AV_SYNC_AA_DROP;
1222 goto done;
1223 }
1224
Song Zhao7daf3a12021-05-10 22:22:25 -07001225 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
1226 avsync->mode == AV_SYNC_MODE_AMASTER) {
1227 action = AV_SYNC_AA_RENDER;
1228 goto done;
1229 }
1230
Song Zhaod62bb392021-04-23 12:25:49 -07001231 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP &&
1232 LIVE_MODE(avsync->mode) &&
1233 abs_diff(systime, pts) > STREAM_DISC_THRES) {
1234 /* outlier by stream error */
1235 avsync->outlier_cnt++;
1236 if (avsync->outlier_cnt > OUTLIER_MAX_CNT) {
1237 /* treat as disc, just drop current frame */
1238 avsync->state = AV_SYNC_STAT_SYNC_LOST;
1239 avsync->outlier_cnt = 0;
1240 action = AV_SYNC_AA_DROP;
1241 systime = pts;
Song Zhaod62bb392021-04-23 12:25:49 -07001242 goto done;
1243 }
1244 log_info("[%d]ignore outlier %u", avsync->session_id, pts);
1245 pts = systime;
1246 action = AV_SYNC_AA_RENDER;
Song Zhao065800e2021-05-26 15:56:06 -07001247 out_lier = true;
Song Zhaod62bb392021-04-23 12:25:49 -07001248 goto done;
1249 }
1250
1251 avsync->outlier_cnt = 0;
1252 /* low bound from sync_lost to sync_setup */
1253 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_LB) {
1254 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
1255 action = AV_SYNC_AA_RENDER;
1256 goto done;
1257 }
1258
1259 /* high bound of sync_setup */
1260 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_HB &&
1261 avsync->state != AV_SYNC_STAT_SYNC_LOST) {
1262 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhaoea5a0412021-01-18 16:40:08 -08001263 action = AV_SYNC_AA_RENDER;
1264 goto done;
1265 }
1266
1267 if ((int)(systime - pts) > 0) {
Song Zhaod62bb392021-04-23 12:25:49 -07001268 avsync->state = AV_SYNC_STAT_SYNC_LOST;
Song Zhaoea5a0412021-01-18 16:40:08 -08001269 action = AV_SYNC_AA_DROP;
1270 goto done;
1271 }
1272
1273 if ((int)(systime - pts) < 0) {
Song Zhaod62bb392021-04-23 12:25:49 -07001274 avsync->state = AV_SYNC_STAT_SYNC_LOST;
Song Zhaoea5a0412021-01-18 16:40:08 -08001275 action = AV_SYNC_AA_INSERT;
1276 goto done;
1277 }
1278
1279done:
1280 policy->action = action;
1281 policy->delta = (int)(systime - pts);
1282 if (action == AV_SYNC_AA_RENDER) {
1283 avsync->apts = pts;
yongchun.li107a6162021-05-05 02:38:57 -07001284 if (!avsync->in_audio_switch) {
Song Zhao065800e2021-05-26 15:56:06 -07001285 if (!out_lier)
1286 msync_session_update_apts(avsync->fd, systime, pts, 0);
Song Zhaof46932e2021-05-21 01:51:45 -07001287 log_debug("[%d]return %d sys %u - pts %u = %d",
Song Zhao409739b2021-05-12 22:21:40 -07001288 avsync->session_id, action, systime, pts, systime - pts);
yongchun.li107a6162021-05-05 02:38:57 -07001289 } else if(avsync->audio_switch_state == AUDIO_SWITCH_STAT_FINISH) {
1290 msync_session_update_apts(avsync->fd, systime, pts, 0);
1291 log_info("[%d] audio switch done sys %u pts %u",
1292 avsync->session_id, systime, pts);
1293 msync_session_set_audio_switch(avsync->fd, false);
1294 avsync->in_audio_switch = false;
1295 avsync->audio_switch_state = AUDIO_SWITCH_STAT_INIT;
1296 } else {
1297 log_trace("[%d] in audio switch ret %d sys %u - pts %u = %d",
1298 avsync->session_id, action, systime, pts, systime - pts);
1299 }
Song Zhaoa2985cb2021-06-24 12:01:47 -07001300 avsync->audio_drop_cnt = 0;
Song Zhaoea5a0412021-01-18 16:40:08 -08001301 } else {
Song Zhaoa2985cb2021-06-24 12:01:47 -07001302 if (abs_diff(systime, pts) > avsync->disc_thres_min &&
yongchun.li085b5a42021-05-24 04:22:53 -07001303 avsync->last_disc_pts != pts &&
1304 !avsync->in_audio_switch) {
Song Zhao409739b2021-05-12 22:21:40 -07001305 log_info ("[%d]audio disc %u --> %u",
1306 avsync->session_id, systime, pts);
1307 msync_session_set_audio_dis(avsync->fd, pts);
1308 avsync->last_disc_pts = pts;
Song Zhaoa2985cb2021-06-24 12:01:47 -07001309 } else if (action == AV_SYNC_AA_DROP) {
yongchun.li0ee6e372021-08-20 04:26:04 -07001310 struct timespec now;
Song Zhaoa2985cb2021-06-24 12:01:47 -07001311
1312 /* dropping recovery */
yongchun.li0ee6e372021-08-20 04:26:04 -07001313 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
Song Zhaoa2985cb2021-06-24 12:01:47 -07001314 if (!avsync->audio_drop_cnt)
1315 avsync->audio_drop_start = now;
1316 avsync->audio_drop_cnt++;
1317 if (time_diff(&now, &avsync->audio_drop_start) > 500000) {
1318 log_info ("[%d]audio keep dropping sys %u vs a %u",
1319 avsync->session_id, systime, pts);
1320 msync_session_set_audio_dis(avsync->fd, pts);
1321 }
Song Zhao409739b2021-05-12 22:21:40 -07001322 }
Song Zhaoa2985cb2021-06-24 12:01:47 -07001323 if (action != AV_SYNC_AA_DROP)
1324 avsync->audio_drop_cnt = 0;
Song Zhaof46932e2021-05-21 01:51:45 -07001325 log_debug("[%d]return %d sys %u - pts %u = %d",
Song Zhaod62bb392021-04-23 12:25:49 -07001326 avsync->session_id, action, systime, pts, systime - pts);
Song Zhaoea5a0412021-01-18 16:40:08 -08001327 }
1328
1329 return ret;
1330}
1331
1332int av_sync_get_clock(void *sync, pts90K *pts)
1333{
1334 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1335
1336 if (!avsync || !pts)
1337 return -1;
1338 return msync_session_get_wall(avsync->fd, pts, NULL);
1339}
1340
1341static void handle_mode_change_a(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -07001342 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -08001343{
bo.xiao1f94b352021-08-02 03:53:47 -04001344 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 -07001345 avsync->active_mode, avsync->mode, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -08001346 if (avsync->active_mode == AV_SYNC_MODE_AMASTER) {
1347 float speed;
1348 if (avsync->start_policy == AV_SYNC_START_ALIGN &&
Song Zhaoe208d692021-04-19 15:38:52 -07001349 a_active && avsync->audio_start) {
yongchun.li107a6162021-05-05 02:38:57 -07001350 if (v_active || v_timeout || avsync->in_audio_switch) {
Song Zhaoe208d692021-04-19 15:38:52 -07001351 log_info("audio start cb");
1352 trigger_audio_start_cb(avsync, AV_SYNC_ASCB_OK);
yongchun.li107a6162021-05-05 02:38:57 -07001353 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001354 }
1355
1356 if (!msync_session_get_rate(avsync->fd, &speed)) {
1357 /* speed change is triggered by asink,
1358 * attached audio HAL will handle it
1359 */
1360 if (speed != avsync->speed)
1361 log_info("[%d]new rate %f", avsync->session_id, speed);
1362 if (speed == 1.0) {
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001363 if (avsync->mode != avsync->backup_mode) {
1364 avsync->mode = avsync->backup_mode;
1365 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
1366 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001367 } else {
1368 avsync->backup_mode = avsync->mode;
1369 avsync->mode = AV_SYNC_MODE_FREE_RUN;
1370 log_info("[%d]audio to freerun mode", avsync->session_id);
1371 }
1372 avsync->speed = speed;
1373 }
Song Zhaod62bb392021-04-23 12:25:49 -07001374 } else if (avsync->active_mode == AV_SYNC_MODE_PCR_MASTER) {
1375 struct session_debug debug;
1376 if (!msync_session_get_debug_mode(avsync->fd, &debug)) {
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001377 if (debug.debug_freerun && !avsync->debug_freerun) {
Song Zhaod62bb392021-04-23 12:25:49 -07001378 avsync->backup_mode = avsync->mode;
1379 avsync->mode = AV_SYNC_MODE_FREE_RUN;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001380 avsync->debug_freerun = true;
Song Zhaod62bb392021-04-23 12:25:49 -07001381 log_warn("[%d]audio to freerun mode", avsync->session_id);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001382 } else if (!debug.debug_freerun && avsync->debug_freerun) {
Song Zhaod62bb392021-04-23 12:25:49 -07001383 avsync->mode = avsync->backup_mode;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001384 avsync->debug_freerun = false;
Song Zhaod62bb392021-04-23 12:25:49 -07001385 log_warn("[%d]audio back to mode %d",
1386 avsync->session_id, avsync->mode);
1387 }
1388 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001389 }
1390}
1391
1392static void handle_mode_change_v(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -07001393 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -08001394{
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001395 struct session_debug debug;
1396
bo.xiao1f94b352021-08-02 03:53:47 -04001397 log_info("[%d]av_sync amode mode %d %d v/a %d/%d", avsync->session_id,
Song Zhaoea5a0412021-01-18 16:40:08 -08001398 avsync->active_mode, avsync->mode, v_active, a_active);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001399 if (!msync_session_get_debug_mode(avsync->fd, &debug)) {
1400 if (debug.debug_freerun && !avsync->debug_freerun) {
1401 avsync->backup_mode = avsync->mode;
1402 avsync->mode = AV_SYNC_MODE_FREE_RUN;
1403 avsync->debug_freerun = true;
1404 log_warn("[%d]video to freerun mode", avsync->session_id);
1405 } else if (!debug.debug_freerun && avsync->debug_freerun) {
1406 avsync->mode = avsync->backup_mode;
1407 avsync->debug_freerun = false;
1408 log_warn("[%d]video back to mode %d",
1409 avsync->session_id, avsync->mode);
Song Zhaod62bb392021-04-23 12:25:49 -07001410 }
1411 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001412}
1413
1414static void * poll_thread(void * arg)
1415{
1416 int ret = 0;
1417 struct av_sync_session *avsync = (struct av_sync_session *)arg;
1418 const int fd = avsync->fd;
1419 struct pollfd pfd = {
1420 /* default blocking capture */
1421 .events = POLLIN | POLLRDNORM | POLLPRI | POLLOUT | POLLWRNORM,
1422 .fd = avsync->fd,
1423 };
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001424 enum src_flag sflag = SRC_A;
Song Zhaoea5a0412021-01-18 16:40:08 -08001425
1426 prctl (PR_SET_NAME, "avs_poll");
1427 log_info("[%d]enter", avsync->session_id);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001428
1429 if (avsync->type == AV_SYNC_TYPE_AUDIO)
1430 sflag = SRC_A;
1431 else if (avsync->type == AV_SYNC_TYPE_VIDEO)
1432 sflag = SRC_V;
1433
Song Zhaoea5a0412021-01-18 16:40:08 -08001434 while (!avsync->quit_poll) {
1435 for (;;) {
1436 ret = poll(&pfd, 1, 10);
1437 if (ret > 0)
1438 break;
1439 if (avsync->quit_poll)
1440 goto exit;
1441 if (errno == EINTR)
1442 continue;
1443 }
1444
1445 /* error handling */
1446 if (pfd.revents & POLLERR)
1447 log_error("[%d]POLLERR received", avsync->session_id);
1448
Song Zhaod62bb392021-04-23 12:25:49 -07001449 /* mode change. Non-exclusive wait so all the processes
1450 * shall be woken up
1451 */
Song Zhaoea5a0412021-01-18 16:40:08 -08001452 if (pfd.revents & POLLPRI) {
Song Zhaoe208d692021-04-19 15:38:52 -07001453 bool v_active, a_active, v_timeout;
Song Zhaoea5a0412021-01-18 16:40:08 -08001454
1455 msync_session_get_stat(fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001456 &v_active, &a_active, &v_timeout, &avsync->in_audio_switch, sflag);
Song Zhaoea5a0412021-01-18 16:40:08 -08001457
1458 if (avsync->type == AV_SYNC_TYPE_AUDIO)
Song Zhaoe208d692021-04-19 15:38:52 -07001459 handle_mode_change_a(avsync, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -08001460 else if (avsync->type == AV_SYNC_TYPE_VIDEO)
Song Zhaoe208d692021-04-19 15:38:52 -07001461 handle_mode_change_v(avsync, v_active, a_active, v_timeout);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001462 usleep(10000);
Song Zhaoea5a0412021-01-18 16:40:08 -08001463 }
1464 }
1465exit:
1466 log_info("[%d]quit", avsync->session_id);
1467 return NULL;
1468}
1469
Song Zhao623e2f12021-09-03 15:54:04 -07001470#define DEMOD_NODE "/sys/class/dtvdemod/atsc_para"
1471/* return ppm between demod and PCR clock */
1472int32_t static dmod_get_sfo_dev(struct av_sync_session *avsync)
1473{
1474 int fd = -1, ppm = 0, nread;
1475 char buf[128];
1476 uint32_t reg_v, lock;
1477 float val;
1478
1479 fd = open(DEMOD_NODE, O_RDWR);
1480 if (fd < 0) {
1481 log_warn("node not found %s", DEMOD_NODE);
1482 /* do not retry */
1483 avsync->ppm_adjusted = true;
1484 return 0;
1485 }
1486 snprintf(buf, sizeof(buf), "%d", 5);
1487 write(fd, buf, 2);
1488
1489 lseek(fd, 0, SEEK_SET);
1490
1491 nread = read(fd, buf, sizeof(buf));
1492 if (nread <= 0) {
1493 log_error("read error");
1494 goto err;
1495 }
1496 buf[nread] = 0;
1497 if (sscanf(buf, "ck=0x%x lock=%d", &reg_v, &lock) != 2) {
1498 log_error("wrong format %s", buf);
1499 goto err;
1500 }
1501 if (lock != 0x1f) {
1502 log_info("demod not locked");
1503 goto err;
1504 }
1505 if (reg_v > ((2 << 20) - 1))
1506 reg_v -= (2 << 21);
1507 val = reg_v * 10.762238f / 12 * 1000000 / (2 << 25);
1508 ppm = val;
1509 log_info("ppm from SFO %d", ppm);
1510 avsync->ppm_adjusted = true;
1511
1512err:
1513 if (fd >= 0)
1514 close(fd);
1515 return ppm;
1516}
1517
Song Zhaod62bb392021-04-23 12:25:49 -07001518int av_sync_set_pcr_clock(void *sync, pts90K pts, uint64_t mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -08001519{
1520 struct av_sync_session *avsync = (struct av_sync_session *)sync;
wei.dubcc2ed22021-05-19 07:16:10 -04001521 struct pcr_info pcr;
1522 enum pcr_monitor_status status;
1523 int ppm;
Song Zhaoea5a0412021-01-18 16:40:08 -08001524 if (!avsync)
1525 return -1;
1526
1527 if (avsync->type != AV_SYNC_TYPE_PCR)
1528 return -2;
1529
Song Zhao623e2f12021-09-03 15:54:04 -07001530 /* initial estimation from Demod SFO HW */
1531 if (!avsync->ppm_adjusted) {
1532 ppm = dmod_get_sfo_dev(avsync);
1533 if (ppm != 0) {
1534 /* ppm > 0 means board clock is faster */
1535 msync_session_set_clock_dev(avsync->fd, -ppm);
1536 }
1537 }
wei.dubcc2ed22021-05-19 07:16:10 -04001538 pcr.monoclk = mono_clock / 1000;
1539 pcr.pts = (long long) pts * 1000 / 90;
1540 pcr_monitor_process(avsync->pcr_monitor, &pcr);
1541
1542 status = pcr_monitor_get_status(avsync->pcr_monitor);
1543
1544 if (status >= DEVIATION_READY) {
1545 pcr_monitor_get_deviation(avsync->pcr_monitor, &ppm);
1546 if (avsync->ppm != ppm) {
1547 avsync->ppm = ppm;
1548 log_info("[%d]ppm:%d", avsync->session_id, ppm);
1549 if (msync_session_set_clock_dev(avsync->fd, ppm))
1550 log_error("set clock dev fail");
Song Zhao623e2f12021-09-03 15:54:04 -07001551 else
1552 avsync->ppm_adjusted = true;
wei.dubcc2ed22021-05-19 07:16:10 -04001553 }
1554 }
1555
Song Zhaod62bb392021-04-23 12:25:49 -07001556 return msync_session_set_pcr(avsync->fd, pts, mono_clock);
Song Zhaoea5a0412021-01-18 16:40:08 -08001557}
1558
Song Zhaod62bb392021-04-23 12:25:49 -07001559int av_sync_get_pcr_clock(void *sync, pts90K *pts, uint64_t * mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -08001560{
1561 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1562
1563 if (!avsync)
1564 return -1;
1565
Song Zhaod62bb392021-04-23 12:25:49 -07001566 return msync_session_get_pcr(avsync->fd, pts, mono_clock);
Song Zhaoea5a0412021-01-18 16:40:08 -08001567}
1568
1569int av_sync_set_session_name(void *sync, const char *name)
1570{
1571 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1572
1573 if (!avsync)
1574 return -1;
1575
1576 return msync_session_set_name(avsync->fd, name);
1577}
yongchun.li107a6162021-05-05 02:38:57 -07001578
1579int av_sync_set_audio_switch(void *sync, bool start)
1580{
1581 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1582 bool v_active, a_active, v_timeout;
1583
1584 if (!avsync)
1585 return -1;
1586 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
1587 &v_active, &a_active,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001588 &v_timeout, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -07001589 log_error("[%d] can not get session state",
1590 avsync->session_id);
1591 return -1;
1592 }
1593 if (!v_active || !a_active) {
1594 log_error("[%d] no apply if not AV both active v %d a %d",
1595 avsync->session_id, v_active, a_active);
1596 return -1;
1597 }
1598 if (msync_session_set_audio_switch(avsync->fd, start)) {
1599 log_error("[%d]fail to set audio switch %d", avsync->session_id, start);
1600 return -1;
1601 }
1602 avsync->in_audio_switch = start;
1603 avsync->audio_switch_state = AUDIO_SWITCH_STAT_INIT;
1604 log_info("[%d]update audio switch to %d", avsync->session_id, start);
1605 return 0;
1606}
1607
1608int av_sync_get_audio_switch(void *sync, bool *start)
1609{
1610 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1611
1612 if (!avsync)
1613 return -1;
1614 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001615 NULL, NULL, NULL, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -07001616 log_error("[%d] can not audio seamless switch state",
1617 avsync->session_id);
1618 return -1;
1619 }
1620 if (start) *start = avsync->in_audio_switch;
1621 return 0;
Song Zhao7daf3a12021-05-10 22:22:25 -07001622}
Song Zhao8039f562021-05-18 18:11:25 -07001623
Song Zhao623e2f12021-09-03 15:54:04 -07001624enum clock_recovery_stat av_sync_get_clock_deviation(void *sync, int32_t *ppm)
Song Zhao8039f562021-05-18 18:11:25 -07001625{
1626 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1627
wei.dubcc2ed22021-05-19 07:16:10 -04001628 if (!avsync || !ppm)
1629 return CLK_RECOVERY_ERR;
1630 if (avsync->mode != AV_SYNC_MODE_PCR_MASTER)
Song Zhao8039f562021-05-18 18:11:25 -07001631 return CLK_RECOVERY_NOT_RUNNING;
1632
wei.dubcc2ed22021-05-19 07:16:10 -04001633 if (msync_session_get_clock_dev(avsync->fd, ppm))
1634 return CLK_RECOVERY_ERR;
1635
1636 if (*ppm == 0)
1637 return CLK_RECOVERY_ONGOING;
1638 else
1639 return CLK_RECOVERY_READY;
Song Zhao8039f562021-05-18 18:11:25 -07001640}
Song Zhao95bd0922021-09-21 14:07:46 -07001641
1642static int video_mono_push_frame(struct av_sync_session *avsync, struct vframe *frame)
1643{
1644 int ret;
1645
1646 if (!avsync->frame_q) {
1647 avsync->frame_q = create_q(MAX_FRAME_NUM);
1648 if (!avsync->frame_q) {
1649 log_error("[%d]create queue fail", avsync->session_id);
1650
1651 return -1;
1652 }
1653 }
1654
1655 ret = queue_item(avsync->frame_q, frame);
1656 if (ret)
1657 log_error("%s queue fail:%d", ret);
1658 log_debug("[%d]push %llu, QNum=%d", avsync->session_id, frame->mts, queue_size(avsync->frame_q));
1659 return ret;
1660}
1661
1662int av_sync_set_vsync_mono_time(void *sync , uint64_t msys)
1663{
1664 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1665
1666 if (!avsync)
1667 return -1;
1668 avsync->msys = msys;
1669 return 0;
1670}
1671
1672static struct vframe * video_mono_pop_frame(struct av_sync_session *avsync)
1673{
1674 struct vframe *frame = NULL, *enter_last_frame = NULL;
1675 uint64_t systime;
1676 int toggle_cnt = 0;
1677
1678 enter_last_frame = avsync->last_frame;
1679 systime = avsync->msys;
1680 log_debug("[%d]sys %llu", avsync->session_id, systime);
1681 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
1682 if (systime >= frame->mts) {
1683 log_debug("[%d]cur_f %llu expire", avsync->session_id, frame->mts);
1684 toggle_cnt++;
1685
1686 if (avsync->last_frame)
1687 avsync->last_holding_peroid = avsync->last_frame->hold_period;
1688
1689 dqueue_item(avsync->frame_q, (void **)&frame);
1690 if (avsync->last_frame) {
1691 /* free frame that are not for display */
1692 if (toggle_cnt > 1) {
1693 log_debug("[%d]free %llu cur %llu system %llu", avsync->session_id,
1694 avsync->last_frame->mts, frame->mts, systime);
1695 avsync->last_frame->free(avsync->last_frame);
1696 }
1697 } else {
1698 avsync->first_frame_toggled = true;
1699 log_info("[%d]first frame %llu", avsync->session_id, frame->mts);
1700 }
1701 avsync->last_frame = frame;
1702 } else
1703 break;
1704 }
1705
1706 if (avsync->last_frame) {
1707 if (enter_last_frame != avsync->last_frame)
1708 log_debug("[%d]pop %llu", avsync->session_id, avsync->last_frame->pts);
1709 log_trace("[%d]pop=%llu, system=%llu, diff %d(ms), QNum=%d", avsync->session_id,
1710 avsync->last_frame->mts,
1711 systime, (systime - avsync->last_frame->mts) / 1000000,
1712 queue_size(avsync->frame_q));
1713 } else
1714 if (enter_last_frame != avsync->last_frame)
1715 log_debug("[%d]pop (nil)", avsync->session_id);
1716
1717 if (avsync->last_frame)
1718 avsync->last_frame->hold_period++;
1719 return avsync->last_frame;
1720}