blob: 3776494a16f5d29e50a87db8bd2893ff57857eb5 [file] [log] [blame]
Song Zhaoc03ba122020-12-23 21:54:02 -08001/*
2 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
3 *
4 * This source code is subject to the terms and conditions defined in the
5 * file 'LICENSE' which is part of this source code package.
6 *
7 * Description:
8 */
Song Zhaoea5a0412021-01-18 16:40:08 -08009#include <errno.h>
Song Zhaoc03ba122020-12-23 21:54:02 -080010#include <pthread.h>
11#include <stdbool.h>
12#include <stdlib.h>
13#include <stdio.h>
14#include <sys/time.h>
Song Zhaoea5a0412021-01-18 16:40:08 -080015#include <poll.h>
16#include <fcntl.h>
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <sys/prctl.h>
20#include <sys/ioctl.h>
Song Zhaoa2985cb2021-06-24 12:01:47 -070021#include <time.h>
Song Zhaoea5a0412021-01-18 16:40:08 -080022#include <unistd.h>
23//#include <linux/amlogic/msync.h>
Song Zhaoc03ba122020-12-23 21:54:02 -080024#include "aml_avsync.h"
25#include "queue.h"
26#include "pattern.h"
Song Zhaoc03ba122020-12-23 21:54:02 -080027#include "aml_avsync_log.h"
Song Zhaoea5a0412021-01-18 16:40:08 -080028#include "msync_util.h"
29#include "msync.h"
30#include <pthread.h>
wei.dubcc2ed22021-05-19 07:16:10 -040031#include "pcr_monitor.h"
Song Zhaoc03ba122020-12-23 21:54:02 -080032enum sync_state {
33 AV_SYNC_STAT_INIT = 0,
34 AV_SYNC_STAT_RUNNING = 1,
35 AV_SYNC_STAT_SYNC_SETUP = 2,
36 AV_SYNC_STAT_SYNC_LOST = 3,
37};
38
yongchun.li107a6162021-05-05 02:38:57 -070039enum audio_switch_state_ {
40 AUDIO_SWITCH_STAT_INIT = 0,
41 AUDIO_SWITCH_STAT_RESET = 1,
42 AUDIO_SWITCH_STAT_START = 2,
43 AUDIO_SWITCH_STAT_FINISH = 3,
yongchun.li59e873d2021-07-07 11:42:38 -070044 AUDIO_SWITCH_STAT_AGAIN = 4,
yongchun.li107a6162021-05-05 02:38:57 -070045};
46
Song Zhaoea5a0412021-01-18 16:40:08 -080047#define SESSION_DEV "avsync_s"
48
Song Zhaoc03ba122020-12-23 21:54:02 -080049struct av_sync_session {
50 /* session id attached */
51 int session_id;
Song Zhaoea5a0412021-01-18 16:40:08 -080052 int fd;
53 bool attached;
54 enum sync_mode mode;
55 /* for audio trickplay */
56 enum sync_mode backup_mode;
57 enum sync_type type;
58 uint32_t start_policy;
bo.xiao5821fc72021-07-11 22:47:00 -040059 int timeout;
Song Zhaoc03ba122020-12-23 21:54:02 -080060
Song Zhaoea5a0412021-01-18 16:40:08 -080061 /* playback time, will stop increasing during pause */
62 pts90K vpts;
63 pts90K apts;
64
65 /* phase adjustment of stream time for rate control (Video ONLY) */
Song Zhaoc03ba122020-12-23 21:54:02 -080066 pts90K phase;
67 bool phase_set;
68
69 /* pts of last rendered frame */
Song Zhaoea5a0412021-01-18 16:40:08 -080070 pts90K last_wall;
Song Zhaoc03ba122020-12-23 21:54:02 -080071 pts90K last_pts;
72 struct vframe *last_frame;
73
Song Zhaoe0bf6ad2021-07-09 11:28:42 -070074 /* pts of last pushed frame */
75 pts90K last_q_pts;
76
Song Zhaoc03ba122020-12-23 21:54:02 -080077 bool first_frame_toggled;
Song Zhaoc03ba122020-12-23 21:54:02 -080078 bool paused;
Song Zhaoea5a0412021-01-18 16:40:08 -080079 enum sync_state state;
Song Zhaoc03ba122020-12-23 21:54:02 -080080 void *pattern_detector;
81 void *frame_q;
Song Zhaoc03ba122020-12-23 21:54:02 -080082
Song Zhaoea5a0412021-01-18 16:40:08 -080083 /* start control */
84 int start_thres;
85 audio_start_cb audio_start;
86 void *audio_start_priv;
87
88 /* render property */
Song Zhaoc03ba122020-12-23 21:54:02 -080089 int delay;
90 pts90K vsync_interval;
91
92 /* state lock */
93 pthread_mutex_t lock;
94 /* pattern */
95 int last_holding_peroid;
Song Zhaoea5a0412021-01-18 16:40:08 -080096 bool session_started;
Song Zhaoc03ba122020-12-23 21:54:02 -080097
98 float speed;
99
Song Zhaoc03ba122020-12-23 21:54:02 -0800100 /* pause pts */
101 pts90K pause_pts;
102 pause_pts_done pause_pts_cb;
103 void *pause_cb_priv;
Song Zhao5d2b4772021-01-18 16:40:08 -0800104
105 /* log control */
Song Zhaoa2985cb2021-06-24 12:01:47 -0700106 uint32_t last_log_syst;
Song Zhao5d2b4772021-01-18 16:40:08 -0800107 uint32_t sync_lost_cnt;
yongchun.li0ee6e372021-08-20 04:26:04 -0700108 struct timespec sync_lost_print_time;
Song Zhaoea5a0412021-01-18 16:40:08 -0800109
110 pthread_t poll_thread;
111 /* pcr master, IPTV only */
112 bool quit_poll;
113 enum sync_mode active_mode;
Song Zhaof46932e2021-05-21 01:51:45 -0700114 uint32_t disc_thres_min;
115 uint32_t disc_thres_max;
Song Zhao35a82df2021-04-15 10:58:49 -0700116
117 /* error detection */
118 uint32_t last_poptime;
Song Zhaod62bb392021-04-23 12:25:49 -0700119 uint32_t outlier_cnt;
Song Zhao409739b2021-05-12 22:21:40 -0700120 pts90K last_disc_pts;
121
yongchun.li107a6162021-05-05 02:38:57 -0700122 // indicate set audio switch
123 bool in_audio_switch;
124 enum audio_switch_state_ audio_switch_state;
wei.dubcc2ed22021-05-19 07:16:10 -0400125
126 //pcr monitor handle
127 void *pcr_monitor;
128 int ppm;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700129
130 //video FPS detection
131 pts90K last_fpts;
132 int fps_interval;
133 int fps_interval_acc;
134 int fps_cnt;
135
136 //video freerun with rate control
137 uint32_t last_r_syst;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700138 bool debug_freerun;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700139
140 //Audio dropping detection
141 uint32_t audio_drop_cnt;
yongchun.li0ee6e372021-08-20 04:26:04 -0700142 struct timespec audio_drop_start;
Song Zhaoc03ba122020-12-23 21:54:02 -0800143};
144
145#define MAX_FRAME_NUM 32
146#define DEFAULT_START_THRESHOLD 2
147#define TIME_UNIT90K (90000)
Song Zhaof46932e2021-05-21 01:51:45 -0700148#define AV_DISC_THRES_MIN (TIME_UNIT90K / 3)
149#define AV_DISC_THRES_MAX (TIME_UNIT90K * 10)
Song Zhao7daf3a12021-05-10 22:22:25 -0700150#define A_ADJ_THREDHOLD_HB (900 * 6) //60ms
151#define A_ADJ_THREDHOLD_LB (900 * 2) //20ms
Song Zhao52f55192021-05-06 10:52:21 -0700152#define AV_PATTERN_RESET_THRES (TIME_UNIT90K / 10)
Song Zhao5d2b4772021-01-18 16:40:08 -0800153#define SYNC_LOST_PRINT_THRESHOLD 10000000 //10 seconds In micro seconds
Song Zhaod62bb392021-04-23 12:25:49 -0700154#define LIVE_MODE(mode) ((mode) == AV_SYNC_MODE_PCR_MASTER || (mode) == AV_SYNC_MODE_IPTV)
155
Song Zhao065800e2021-05-26 15:56:06 -0700156#define STREAM_DISC_THRES (TIME_UNIT90K / 10)
Song Zhaod62bb392021-04-23 12:25:49 -0700157#define OUTLIER_MAX_CNT 8
Song Zhaoa2985cb2021-06-24 12:01:47 -0700158#define VALID_TS(x) ((x) != -1)
Song Zhaoc03ba122020-12-23 21:54:02 -0800159
yongchun.li0ee6e372021-08-20 04:26:04 -0700160static uint64_t time_diff (struct timespec *b, struct timespec *a);
Song Zhaoc03ba122020-12-23 21:54:02 -0800161static bool frame_expire(struct av_sync_session* avsync,
162 uint32_t systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800163 uint32_t interval,
Song Zhaoc03ba122020-12-23 21:54:02 -0800164 struct vframe * frame,
165 struct vframe * next_frame,
166 int toggle_cnt);
Song Zhao35a82df2021-04-15 10:58:49 -0700167static bool pattern_detect(struct av_sync_session* avsync,
Song Zhaoc03ba122020-12-23 21:54:02 -0800168 int cur_period,
169 int last_period);
Song Zhaoea5a0412021-01-18 16:40:08 -0800170static void * poll_thread(void * arg);
171static void trigger_audio_start_cb(struct av_sync_session *avsync,
172 avs_ascb_reason reason);
Song Zhaoc03ba122020-12-23 21:54:02 -0800173
Song Zhaoea5a0412021-01-18 16:40:08 -0800174int av_sync_open_session(int *session_id)
175{
176 int fd = msync_create_session();
177 int id, rc;
178
179 if (fd < 0) {
180 log_error("fail");
181 return -1;
182 }
183 rc = ioctl(fd, AMSYNC_IOC_ALLOC_SESSION, &id);
184 if (rc) {
185 log_error("new session errno:%d", errno);
186 return rc;
187 }
188 *session_id = id;
189 return fd;
190}
191
192void av_sync_close_session(int session)
193{
194 msync_destory_session(session);
195}
196
197static void* create_internal(int session_id,
Song Zhaoc03ba122020-12-23 21:54:02 -0800198 enum sync_mode mode,
Song Zhaoea5a0412021-01-18 16:40:08 -0800199 enum sync_type type,
Song Zhaoc03ba122020-12-23 21:54:02 -0800200 int start_thres,
Song Zhaoea5a0412021-01-18 16:40:08 -0800201 bool attach)
Song Zhaoc03ba122020-12-23 21:54:02 -0800202{
203 struct av_sync_session *avsync = NULL;
Song Zhaoea5a0412021-01-18 16:40:08 -0800204 char dev_name[20];
Song Zhaoc03ba122020-12-23 21:54:02 -0800205
206 avsync = (struct av_sync_session *)calloc(1, sizeof(*avsync));
207 if (!avsync) {
208 log_error("OOM");
209 return NULL;
210 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800211
212 if (type == AV_SYNC_TYPE_VIDEO) {
213 avsync->pattern_detector = create_pattern_detector();
214 if (!avsync->pattern_detector) {
215 log_error("pd create fail");
216 goto err;
217 }
218
219 if (!start_thres)
220 avsync->start_thres = DEFAULT_START_THRESHOLD;
221 else {
222 if (start_thres > 5) {
223 log_error("start_thres too big: %d", start_thres);
224 goto err2;
225 }
226 avsync->start_thres = start_thres;
227 }
228 avsync->phase_set = false;
229 avsync->first_frame_toggled = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800230 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800231
232 avsync->type = type;
Song Zhaoc03ba122020-12-23 21:54:02 -0800233 avsync->state = AV_SYNC_STAT_INIT;
Song Zhaoc03ba122020-12-23 21:54:02 -0800234 avsync->paused = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800235 avsync->session_id = session_id;
Song Zhaoea5a0412021-01-18 16:40:08 -0800236 avsync->backup_mode = mode;
Song Zhaoc03ba122020-12-23 21:54:02 -0800237 avsync->last_frame = NULL;
Song Zhaoea5a0412021-01-18 16:40:08 -0800238 avsync->session_started = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800239 avsync->speed = 1.0f;
240 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
Song Zhao409739b2021-05-12 22:21:40 -0700241 avsync->vsync_interval = -1;
242 avsync->last_disc_pts = -1;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700243 avsync->last_log_syst = -1;
244 avsync->last_pts = -1;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700245 avsync->last_q_pts = -1;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700246 avsync->last_wall = -1;
247 avsync->fps_interval = -1;
248 avsync->last_r_syst = -1;
bo.xiao5821fc72021-07-11 22:47:00 -0400249 avsync->timeout = -1;
250
Song Zhaof46932e2021-05-21 01:51:45 -0700251 if (msync_session_get_disc_thres(session_id,
252 &avsync->disc_thres_min, &avsync->disc_thres_max)) {
253 log_error("fail to get disc thres", dev_name, errno);
254 avsync->disc_thres_min = AV_DISC_THRES_MIN;
255 avsync->disc_thres_max = AV_DISC_THRES_MAX;
256 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800257
258 pthread_mutex_init(&avsync->lock, NULL);
Song Zhaof46932e2021-05-21 01:51:45 -0700259 log_info("[%d] mode %d type %d start_thres %d disc_thres %u/%u",
260 session_id, mode, type, start_thres,
261 avsync->disc_thres_min, avsync->disc_thres_max);
Song Zhaoea5a0412021-01-18 16:40:08 -0800262
263 snprintf(dev_name, sizeof(dev_name), "/dev/%s%d", SESSION_DEV, session_id);
264 avsync->fd = open(dev_name, O_RDONLY | O_CLOEXEC);
265 if (avsync->fd < 0) {
266 log_error("open %s errno %d", dev_name, errno);
267 goto err2;
268 }
269
wei.dubcc2ed22021-05-19 07:16:10 -0400270 if (avsync->type == AV_SYNC_TYPE_PCR) {
271 if (pcr_monitor_init(&avsync->pcr_monitor)) {
272 log_error("pcr monitor init");
Song Zhao9cd27a52021-07-26 15:27:38 +0000273 goto err3;
wei.dubcc2ed22021-05-19 07:16:10 -0400274 }
275 }
276
Song Zhaoea5a0412021-01-18 16:40:08 -0800277 if (!attach) {
278 msync_session_set_mode(avsync->fd, mode);
279 avsync->mode = mode;
280 } else {
281 avsync->attached = true;
282 if (msync_session_get_mode(avsync->fd, &avsync->mode)) {
283 log_error("get mode");
Song Zhao9cd27a52021-07-26 15:27:38 +0000284 goto err4;
Song Zhaoea5a0412021-01-18 16:40:08 -0800285 }
286 avsync->backup_mode = avsync->mode;
bo.xiao5821fc72021-07-11 22:47:00 -0400287 if (msync_session_get_start_policy(avsync->fd, &avsync->start_policy, &avsync->timeout)) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800288 log_error("get policy");
Song Zhao9cd27a52021-07-26 15:27:38 +0000289 goto err4;
Song Zhaoea5a0412021-01-18 16:40:08 -0800290 }
yongchun.li107a6162021-05-05 02:38:57 -0700291 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700292 NULL, NULL, NULL, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -0700293 log_error("get state");
Song Zhao9cd27a52021-07-26 15:27:38 +0000294 goto err4;
yongchun.li107a6162021-05-05 02:38:57 -0700295 }
296 if (avsync->in_audio_switch) {
297 log_info("audio_switch_state reseted the audio");
298 avsync->audio_switch_state = AUDIO_SWITCH_STAT_RESET;
299 }
300
Song Zhaoea5a0412021-01-18 16:40:08 -0800301 log_info("[%d]retrieve sync mode %d policy %d",
302 session_id, avsync->mode, avsync->start_policy);
303 }
304
Song Zhaoc03ba122020-12-23 21:54:02 -0800305 return avsync;
Song Zhao9cd27a52021-07-26 15:27:38 +0000306err4:
wei.dubcc2ed22021-05-19 07:16:10 -0400307 if (avsync->pcr_monitor)
308 pcr_monitor_destroy(avsync->pcr_monitor);
Song Zhao9cd27a52021-07-26 15:27:38 +0000309err3:
310 close(avsync->fd);
Song Zhaoea5a0412021-01-18 16:40:08 -0800311err2:
312 destroy_pattern_detector(avsync->pattern_detector);
313err:
314 free(avsync);
315 return NULL;
316}
317
318void* av_sync_create(int session_id,
319 enum sync_mode mode,
320 enum sync_type type,
321 int start_thres)
322{
323 return create_internal(session_id, mode,
324 type, start_thres, false);
325}
326
327void* av_sync_attach(int session_id, enum sync_type type)
328{
329 return create_internal(session_id, AV_SYNC_MODE_MAX,
330 type, 0, true);
331}
332
333int av_sync_video_config(void *sync, struct video_config* config)
334{
335 struct av_sync_session *avsync = (struct av_sync_session *)sync;
336
337 if (!avsync || !config)
338 return -1;
339
340 if (config->delay != 1 && config->delay != 2) {
341 log_error("invalid delay: %d\n", config->delay);
342 return -1;
343 }
344
345 avsync->delay = config->delay;
346
347 log_info("[%d] delay: %d",
348 avsync->session_id, config->delay);
349 return 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800350}
351
352static int internal_stop(struct av_sync_session *avsync)
353{
354 int ret = 0;
355 struct vframe *frame;
356
357 pthread_mutex_lock(&avsync->lock);
Song Zhaoc03ba122020-12-23 21:54:02 -0800358 while (!dqueue_item(avsync->frame_q, (void **)&frame)) {
359 frame->free(frame);
360 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800361 avsync->state = AV_SYNC_STAT_INIT;
Song Zhaoc03ba122020-12-23 21:54:02 -0800362 pthread_mutex_unlock(&avsync->lock);
363 return ret;
364}
365
366/* destroy and detach from kernel session */
367void av_sync_destroy(void *sync)
368{
369 struct av_sync_session *avsync = (struct av_sync_session *)sync;
370
371 if (!avsync)
372 return;
373
Song Zhaoea5a0412021-01-18 16:40:08 -0800374 log_info("[%d]begin", avsync->session_id);
375 if (avsync->state != AV_SYNC_STAT_INIT) {
376 if (avsync->type == AV_SYNC_TYPE_VIDEO)
377 internal_stop(avsync);
Song Zhaoc03ba122020-12-23 21:54:02 -0800378
Song Zhaoea5a0412021-01-18 16:40:08 -0800379 avsync->quit_poll = true;
380 if (avsync->poll_thread) {
381 pthread_join(avsync->poll_thread, NULL);
382 avsync->poll_thread = 0;
383 }
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700384 if (avsync->type == AV_SYNC_TYPE_AUDIO)
385 trigger_audio_start_cb(avsync, AV_SYNC_ASCB_STOP);
Song Zhaoaf368d52021-02-17 17:53:45 -0800386 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800387
Song Zhaoea5a0412021-01-18 16:40:08 -0800388 if (avsync->session_started) {
389 if (avsync->type == AV_SYNC_TYPE_VIDEO)
390 msync_session_set_video_stop(avsync->fd);
391 else
392 msync_session_set_audio_stop(avsync->fd);
393 }
wei.dubcc2ed22021-05-19 07:16:10 -0400394
395 if(avsync->pcr_monitor)
396 pcr_monitor_destroy(avsync->pcr_monitor);
397
Song Zhaoea5a0412021-01-18 16:40:08 -0800398 close(avsync->fd);
Song Zhaoc03ba122020-12-23 21:54:02 -0800399 pthread_mutex_destroy(&avsync->lock);
Song Zhaoea5a0412021-01-18 16:40:08 -0800400 if (avsync->type == AV_SYNC_TYPE_VIDEO) {
401 destroy_q(avsync->frame_q);
402 destroy_pattern_detector(avsync->pattern_detector);
403 }
404 log_info("[%d]done", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800405 free(avsync);
Song Zhaoea5a0412021-01-18 16:40:08 -0800406}
407
bo.xiao5821fc72021-07-11 22:47:00 -0400408int avs_sync_set_start_policy(void *sync, struct start_policy* st_policy)
Song Zhaoea5a0412021-01-18 16:40:08 -0800409{
410 struct av_sync_session *avsync = (struct av_sync_session *)sync;
411
412 if (!avsync || !avsync->fd)
413 return -1;
414
bo.xiao5821fc72021-07-11 22:47:00 -0400415 log_info("[%d]policy %u --> %u, timeout %d --> %d", avsync->start_policy, st_policy->policy, avsync->timeout, st_policy->timeout);
416 avsync->start_policy = st_policy->policy;
417 avsync->timeout = st_policy->timeout;
Song Zhaoea5a0412021-01-18 16:40:08 -0800418 /* v_peek will be handled by libamlavsync */
bo.xiao5821fc72021-07-11 22:47:00 -0400419 if (st_policy->policy != AV_SYNC_START_NONE &&
420 st_policy->policy != AV_SYNC_START_V_PEEK)
421 return msync_session_set_start_policy(avsync->fd, st_policy->policy, st_policy->timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -0800422
423 return 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800424}
425
426int av_sync_pause(void *sync, bool pause)
427{
428 struct av_sync_session *avsync = (struct av_sync_session *)sync;
yongchun.li107a6162021-05-05 02:38:57 -0700429 bool v_active, a_active, v_timeout;
Song Zhaoea5a0412021-01-18 16:40:08 -0800430 int rc;
Song Zhaoc03ba122020-12-23 21:54:02 -0800431
432 if (!avsync)
433 return -1;
434
Song Zhaoea5a0412021-01-18 16:40:08 -0800435 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER)
436 return -1;
Song Zhaoc03ba122020-12-23 21:54:02 -0800437
yongchun.li107a6162021-05-05 02:38:57 -0700438 rc = msync_session_get_stat(avsync->fd, &avsync->active_mode,
439 &v_active, &a_active, &v_timeout,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700440 &avsync->in_audio_switch, SRC_A);
yongchun.li107a6162021-05-05 02:38:57 -0700441
yongchun.li5f52fb02021-06-04 18:13:05 -0700442 /* ignore only when video try to pause when audio is acive, on which
443 the control of the STC will be relays.
444 When resume,it can do always as it is possible that video just
445 paused earlier without audio yet,then audio added later before resume.
446 We shall not igore that otherwise it could cause video freeze. */
447 if (avsync->mode == AV_SYNC_MODE_AMASTER &&
448 avsync->type == AV_SYNC_TYPE_VIDEO &&
449 a_active &&
450 !avsync->in_audio_switch) {
451 if (!pause) {
452 log_info("[%d] clear video pause when audio active",
453 avsync->session_id);
454 avsync->paused = pause;
455 } else {
456 log_info("[%d] ignore the pause from video when audio active",
457 avsync->session_id);
458 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800459 return 0;
yongchun.li5f52fb02021-06-04 18:13:05 -0700460 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800461
yongchun.li107a6162021-05-05 02:38:57 -0700462 if (avsync->in_audio_switch && avsync->type == AV_SYNC_TYPE_AUDIO) {
463 log_info("[%d] ignore the pause from audio", avsync->session_id);
464 avsync->audio_switch_state = AUDIO_SWITCH_STAT_RESET;
465 return 0;
466 }
467
Song Zhaoea5a0412021-01-18 16:40:08 -0800468 rc = msync_session_set_pause(avsync->fd, pause);
Song Zhaoc03ba122020-12-23 21:54:02 -0800469 avsync->paused = pause;
Song Zhaoea5a0412021-01-18 16:40:08 -0800470 log_info("[%d]paused:%d type:%d rc %d",
471 avsync->session_id, pause, avsync->type, rc);
Song Zhaoc03ba122020-12-23 21:54:02 -0800472
Song Zhaoea5a0412021-01-18 16:40:08 -0800473 return rc;
Song Zhaoc03ba122020-12-23 21:54:02 -0800474}
475
476int av_sync_push_frame(void *sync , struct vframe *frame)
477{
478 int ret;
Song Zhaoee6a1512021-09-08 11:28:57 -0700479 struct vframe *prev = NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800480 struct av_sync_session *avsync = (struct av_sync_session *)sync;
481
482 if (!avsync)
483 return -1;
484
Song Zhaoea5a0412021-01-18 16:40:08 -0800485 if (!avsync->frame_q) {
486 /* policy should be final now */
bo.xiao5821fc72021-07-11 22:47:00 -0400487 if (msync_session_get_start_policy(avsync->fd, &avsync->start_policy, &avsync->timeout)) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800488 log_error("[%d]get policy", avsync->session_id);
489 return -1;
490 }
491
492 avsync->frame_q = create_q(MAX_FRAME_NUM);
493 if (!avsync->frame_q) {
494 log_error("[%d]create queue fail", avsync->session_id);
yongchun.li0ee6e372021-08-20 04:26:04 -0700495
Song Zhaoea5a0412021-01-18 16:40:08 -0800496 return -1;
497 }
498
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700499 /* for debugging */
500 {
Song Zhaoea5a0412021-01-18 16:40:08 -0800501 int ret;
502
503 ret = pthread_create(&avsync->poll_thread, NULL, poll_thread, avsync);
504 if (ret) {
505 log_error("[%d]create poll thread errno %d", avsync->session_id, errno);
506 destroy_q(avsync->frame_q);
507 return -1;
508 }
509 }
510 }
511
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700512 if (avsync->last_q_pts != -1) {
513 if (avsync->last_q_pts == frame->pts && avsync->mode == AV_SYNC_MODE_AMASTER) {
514 /* TODO: wrong, should remove from back of queue */
Song Zhaoc03ba122020-12-23 21:54:02 -0800515 dqueue_item(avsync->frame_q, (void **)&prev);
Song Zhaoee6a1512021-09-08 11:28:57 -0700516 if (prev) {
517 prev->free(prev);
518 log_info ("[%d]drop frame with same pts %u", avsync->session_id, frame->pts);
519 }
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700520 } else if (avsync->fps_cnt < 100) {
521 int32_t interval = frame->pts - avsync->last_q_pts;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700522
523 if (interval > 0 && interval <= 4500) {
524 if (avsync->fps_interval_acc == -1) {
525 avsync->fps_interval_acc = interval;
526 avsync->fps_cnt = 1;
527 } else {
528 avsync->fps_interval_acc += interval;
529 avsync->fps_cnt++;
530 avsync->fps_interval = avsync->fps_interval_acc / avsync->fps_cnt;
531 if (avsync->fps_cnt == 100)
532 log_info("[%d] fps_interval = %d", avsync->session_id, avsync->fps_interval);
533 }
534 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800535 }
536 }
537
Song Zhao065800e2021-05-26 15:56:06 -0700538 if (frame->duration == -1)
539 frame->duration = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800540 frame->hold_period = 0;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700541 avsync->last_q_pts = frame->pts;
Song Zhaoc03ba122020-12-23 21:54:02 -0800542 ret = queue_item(avsync->frame_q, frame);
543 if (avsync->state == AV_SYNC_STAT_INIT &&
544 queue_size(avsync->frame_q) >= avsync->start_thres) {
545 avsync->state = AV_SYNC_STAT_RUNNING;
Song Zhaoea5a0412021-01-18 16:40:08 -0800546 log_info("[%d]state: init --> running", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800547 }
548
549 if (ret)
550 log_error("%s queue fail:%d", ret);
bo.xiao1f94b352021-08-02 03:53:47 -0400551 log_debug("[%d]push %u, QNum=%d", avsync->session_id, frame->pts, queue_size(avsync->frame_q));
Song Zhaoc03ba122020-12-23 21:54:02 -0800552 return ret;
553
554}
555
556struct vframe *av_sync_pop_frame(void *sync)
557{
Song Zhaoea5a0412021-01-18 16:40:08 -0800558 struct vframe *frame = NULL, *enter_last_frame = NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800559 struct av_sync_session *avsync = (struct av_sync_session *)sync;
560 int toggle_cnt = 0;
561 uint32_t systime;
Song Zhao468fd652021-01-15 22:13:04 -0800562 bool pause_pts_reached = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800563 uint32_t interval;
Song Zhaoc03ba122020-12-23 21:54:02 -0800564
565 pthread_mutex_lock(&avsync->lock);
566 if (avsync->state == AV_SYNC_STAT_INIT) {
Song Zhaod62bb392021-04-23 12:25:49 -0700567 log_info("[%d]in state INIT", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800568 goto exit;
569 }
570
Song Zhaoea5a0412021-01-18 16:40:08 -0800571 if (!avsync->session_started) {
Song Zhao35a82df2021-04-15 10:58:49 -0700572 uint32_t pts;
573
Song Zhaoc03ba122020-12-23 21:54:02 -0800574 if (peek_item(avsync->frame_q, (void **)&frame, 0) || !frame) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800575 log_info("[%d]empty q", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800576 goto exit;
577 }
Song Zhao35a82df2021-04-15 10:58:49 -0700578 msync_session_get_wall(avsync->fd, &systime, &interval);
579 pts = frame->pts - avsync->delay * interval;
580 msync_session_set_video_start(avsync->fd, pts);
Song Zhaoea5a0412021-01-18 16:40:08 -0800581 avsync->session_started = true;
Song Zhao35a82df2021-04-15 10:58:49 -0700582 log_info("[%d]video start %u", avsync->session_id, pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800583 }
584
Song Zhaoea5a0412021-01-18 16:40:08 -0800585 if (avsync->start_policy == AV_SYNC_START_ALIGN &&
Song Zhaod4109b62021-04-30 08:47:17 -0700586 !avsync->first_frame_toggled &&
587 !msync_clock_started(avsync->fd)) {
588 pthread_mutex_unlock(&avsync->lock);
Song Zhaoea5a0412021-01-18 16:40:08 -0800589 log_trace("[%d]clock not started", avsync->session_id);
590 return NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800591 }
592
Song Zhaoea5a0412021-01-18 16:40:08 -0800593 enter_last_frame = avsync->last_frame;
594 msync_session_get_wall(avsync->fd, &systime, &interval);
595
596 /* handle refresh rate change */
597 if (avsync->vsync_interval == AV_SYNC_INVALID_PAUSE_PTS ||
598 avsync->vsync_interval != interval) {
599 log_info("[%d]vsync interval update %d --> %u",
600 avsync->session_id, avsync->vsync_interval, interval);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700601 if (avsync->fps_interval == -1)
602 avsync->fps_interval = interval;
Song Zhaoea5a0412021-01-18 16:40:08 -0800603 avsync->vsync_interval = interval;
604 avsync->phase_set = false;
Song Zhaode5f73b2021-07-23 22:38:07 -0700605 avsync->phase = 0;
Song Zhaoea5a0412021-01-18 16:40:08 -0800606 reset_pattern(avsync->pattern_detector);
607 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800608 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
609 struct vframe *next_frame = NULL;
610
611 peek_item(avsync->frame_q, (void **)&next_frame, 1);
612 if (next_frame)
Song Zhaof46932e2021-05-21 01:51:45 -0700613 log_debug("[%d]cur_f %u next_f %u size %d",
614 avsync->session_id, frame->pts, next_frame->pts, queue_size(avsync->frame_q));
Song Zhaoea5a0412021-01-18 16:40:08 -0800615 if (frame_expire(avsync, systime, interval,
616 frame, next_frame, toggle_cnt)) {
617 log_debug("[%d]cur_f %u expire", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800618 toggle_cnt++;
619
Song Zhao35a82df2021-04-15 10:58:49 -0700620 if (pattern_detect(avsync,
Song Zhaoc03ba122020-12-23 21:54:02 -0800621 (avsync->last_frame?avsync->last_frame->hold_period:0),
Song Zhao35a82df2021-04-15 10:58:49 -0700622 avsync->last_holding_peroid))
623 log_info("[%d] %u break the pattern", avsync->session_id, avsync->last_frame->pts);
624
Song Zhaoc03ba122020-12-23 21:54:02 -0800625 if (avsync->last_frame)
626 avsync->last_holding_peroid = avsync->last_frame->hold_period;
627
628 dqueue_item(avsync->frame_q, (void **)&frame);
629 if (avsync->last_frame) {
630 /* free frame that are not for display */
Song Zhaoea5a0412021-01-18 16:40:08 -0800631 if (toggle_cnt > 1) {
Song Zhao35a82df2021-04-15 10:58:49 -0700632 log_debug("[%d]free %u cur %u system/d %u/%u", avsync->session_id,
633 avsync->last_frame->pts, frame->pts, systime, systime - avsync->last_poptime);
Song Zhaoc03ba122020-12-23 21:54:02 -0800634 avsync->last_frame->free(avsync->last_frame);
Song Zhaoea5a0412021-01-18 16:40:08 -0800635 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800636 } else {
637 avsync->first_frame_toggled = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800638 log_info("[%d]first frame %u", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800639 }
640 avsync->last_frame = frame;
Song Zhao5d2b4772021-01-18 16:40:08 -0800641 avsync->last_pts = frame->pts;
Song Zhaoc03ba122020-12-23 21:54:02 -0800642 } else
643 break;
644 }
645
646 /* pause pts */
647 if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS && avsync->last_frame) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800648 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
Song Zhao468fd652021-01-15 22:13:04 -0800649 pause_pts_reached = true;
Song Zhaoc03ba122020-12-23 21:54:02 -0800650 else
Song Zhao468fd652021-01-15 22:13:04 -0800651 pause_pts_reached = (int)(avsync->last_frame->pts - avsync->pause_pts) >= 0;
652 } else if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS) {
653 if (!peek_item(avsync->frame_q, (void **)&frame, 0))
654 pause_pts_reached = (int)(frame->pts - avsync->pause_pts) >= 0;
655 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800656
Song Zhao468fd652021-01-15 22:13:04 -0800657 if (pause_pts_reached) {
658 if (avsync->pause_pts_cb)
659 avsync->pause_pts_cb(avsync->pause_pts,
Song Zhaoc03ba122020-12-23 21:54:02 -0800660 avsync->pause_cb_priv);
661
Song Zhao468fd652021-01-15 22:13:04 -0800662 /* stay in paused until av_sync_pause(false) */
663 avsync->paused = true;
664 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
Song Zhaoea5a0412021-01-18 16:40:08 -0800665 log_info ("[%d]reach pause pts: %u",
666 avsync->session_id, avsync->last_frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800667 }
668
669exit:
670 pthread_mutex_unlock(&avsync->lock);
671 if (avsync->last_frame) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800672 if (enter_last_frame != avsync->last_frame)
673 log_debug("[%d]pop %u", avsync->session_id, avsync->last_frame->pts);
bo.xiao1f94b352021-08-02 03:53:47 -0400674 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 -0700675 /* don't update vpts for out_lier */
676 if (avsync->last_frame->duration != -1)
677 msync_session_update_vpts(avsync->fd, systime,
678 avsync->last_frame->pts, interval * avsync->delay);
Song Zhaoc03ba122020-12-23 21:54:02 -0800679 } else
Song Zhaoea5a0412021-01-18 16:40:08 -0800680 if (enter_last_frame != avsync->last_frame)
681 log_debug("[%d]pop (nil)", avsync->session_id);
682
Song Zhao35a82df2021-04-15 10:58:49 -0700683 avsync->last_poptime = systime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800684 if (avsync->last_frame)
685 avsync->last_frame->hold_period++;
686 return avsync->last_frame;
687}
688
Song Zhaoc03ba122020-12-23 21:54:02 -0800689static inline uint32_t abs_diff(uint32_t a, uint32_t b)
690{
Song Zhaoea5a0412021-01-18 16:40:08 -0800691 return (int)(a - b) > 0 ? a - b : b - a;
Song Zhaoc03ba122020-12-23 21:54:02 -0800692}
693
yongchun.li0ee6e372021-08-20 04:26:04 -0700694static uint64_t time_diff (struct timespec *b, struct timespec *a)
Song Zhaoc03ba122020-12-23 21:54:02 -0800695{
yongchun.li0ee6e372021-08-20 04:26:04 -0700696 return (b->tv_sec - a->tv_sec)*1000000 + (b->tv_nsec/1000 - a->tv_nsec/1000);
Song Zhaoc03ba122020-12-23 21:54:02 -0800697}
698
Song Zhaoc03ba122020-12-23 21:54:02 -0800699static bool frame_expire(struct av_sync_session* avsync,
700 uint32_t systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800701 uint32_t interval,
Song Zhaoc03ba122020-12-23 21:54:02 -0800702 struct vframe * frame,
703 struct vframe * next_frame,
704 int toggle_cnt)
705{
706 uint32_t fpts = frame->pts;
707 bool expire = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800708 uint32_t pts_correction = avsync->delay * interval;
Song Zhaoc03ba122020-12-23 21:54:02 -0800709
710 if (avsync->paused && avsync->pause_pts == AV_SYNC_INVALID_PAUSE_PTS)
711 return false;
712
713 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
714 return true;
715
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700716 if (avsync->mode == AV_SYNC_MODE_FREE_RUN) {
717 /* render according to FPS */
718 if (!VALID_TS(avsync->last_r_syst) ||
719 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
720 avsync->last_r_syst = systime;
721 return true;
722 }
723 return false;
724 }
725
Song Zhaoc03ba122020-12-23 21:54:02 -0800726 if (!fpts) {
727 if (avsync->last_frame) {
728 /* try to accumulate duration as PTS */
729 fpts = avsync->vpts + avsync->last_frame->duration;
730 } else {
731 fpts = avsync->vpts;
732 }
733 }
734 systime += pts_correction;
735
736 /* phase adjustment */
737 if (avsync->phase_set)
738 systime += avsync->phase;
739
yongchun.lia50b1e92021-08-07 01:11:54 +0000740 log_trace("[%d]systime:%u phase:%d correct:%u fpts:%u",
Song Zhaoea5a0412021-01-18 16:40:08 -0800741 avsync->session_id, systime,
yongchun.lia50b1e92021-08-07 01:11:54 +0000742 avsync->phase_set? (int)avsync->phase:0, pts_correction, fpts);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700743 if (abs_diff(systime, fpts) > avsync->disc_thres_min) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800744 /* ignore discontinity under pause */
Song Zhaoea5a0412021-01-18 16:40:08 -0800745 if (avsync->paused)
Song Zhaoc03ba122020-12-23 21:54:02 -0800746 return false;
747
Song Zhaoa2985cb2021-06-24 12:01:47 -0700748 if ((VALID_TS(avsync->last_log_syst) && avsync->last_log_syst != systime) ||
749 (VALID_TS(avsync->last_pts) && avsync->last_pts != fpts)) {
yongchun.li0ee6e372021-08-20 04:26:04 -0700750 struct timespec now;
Song Zhao5d2b4772021-01-18 16:40:08 -0800751
yongchun.li0ee6e372021-08-20 04:26:04 -0700752 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700753 avsync->last_log_syst = systime;
Song Zhao5d2b4772021-01-18 16:40:08 -0800754 avsync->last_pts = fpts;
755 if (time_diff(&now, &avsync->sync_lost_print_time) >=
756 SYNC_LOST_PRINT_THRESHOLD) {
Song Zhaof46932e2021-05-21 01:51:45 -0700757 log_warn("[%d]sync lost systime:%u fpts:%u lost:%u",
Song Zhaoea5a0412021-01-18 16:40:08 -0800758 avsync->session_id, systime, fpts, avsync->sync_lost_cnt);
Song Zhao5d2b4772021-01-18 16:40:08 -0800759 avsync->sync_lost_cnt = 0;
yongchun.li0ee6e372021-08-20 04:26:04 -0700760 clock_gettime(CLOCK_MONOTONIC_RAW, &avsync->sync_lost_print_time);
Song Zhao5d2b4772021-01-18 16:40:08 -0800761 } else
762 avsync->sync_lost_cnt++;
763 }
Song Zhaod62bb392021-04-23 12:25:49 -0700764
765 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP &&
766 LIVE_MODE(avsync->mode) &&
Song Zhaoa2985cb2021-06-24 12:01:47 -0700767 VALID_TS(avsync->last_pts) &&
Song Zhao065800e2021-05-26 15:56:06 -0700768 abs_diff(avsync->last_pts, fpts) > STREAM_DISC_THRES) {
Song Zhaod62bb392021-04-23 12:25:49 -0700769 /* outlier by stream error */
770 avsync->outlier_cnt++;
Song Zhao065800e2021-05-26 15:56:06 -0700771 frame->duration = -1;
Song Zhaod62bb392021-04-23 12:25:49 -0700772 if (avsync->outlier_cnt < OUTLIER_MAX_CNT) {
773 log_info("render outlier %u", fpts);
774 return true;
775 }
776 }
777
778 avsync->outlier_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800779 avsync->state = AV_SYNC_STAT_SYNC_LOST;
780 avsync->phase_set = false;
Song Zhaode5f73b2021-07-23 22:38:07 -0700781 avsync->phase = 0;
Song Zhaoa58c3e92021-03-09 18:52:55 -0800782 reset_pattern(avsync->pattern_detector);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700783
784 if (LIVE_MODE(avsync->mode) && avsync->last_disc_pts != fpts) {
Song Zhaod62bb392021-04-23 12:25:49 -0700785 log_info ("[%d]video disc %u --> %u",
Song Zhaoa2985cb2021-06-24 12:01:47 -0700786 avsync->session_id, systime, fpts);
Song Zhao409739b2021-05-12 22:21:40 -0700787 msync_session_set_video_dis(avsync->fd, fpts);
788 avsync->last_disc_pts = fpts;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700789 }
790
791 if ((int)(systime - fpts) > 0) {
792 if ((int)(systime - fpts) < avsync->disc_thres_max) {
793 /* catch up PCR */
Song Zhaof46932e2021-05-21 01:51:45 -0700794 return true;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700795 } else {
796 /* render according to FPS */
797 if (!VALID_TS(avsync->last_r_syst) ||
798 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
799 avsync->last_r_syst = systime;
800 return true;
801 }
802 return false;
803 }
804 } else if (LIVE_MODE(avsync->mode)) {
805 /* hold if the gap is small */
806 if ((int)(fpts - systime) < avsync->disc_thres_max) {
807 return false;
808 } else {
809 /* render according to FPS */
810 if (!VALID_TS(avsync->last_r_syst) ||
811 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
812 avsync->last_r_syst = systime;
813 return true;
814 }
815 return false;
816 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800817 }
818 }
819
Song Zhao52f55192021-05-06 10:52:21 -0700820 /* In some cases, keeping pattern will enlarge the gap */
821 if (abs_diff(systime, fpts) > AV_PATTERN_RESET_THRES &&
822 avsync->first_frame_toggled) {
823 reset_pattern(avsync->pattern_detector);
Song Zhaof46932e2021-05-21 01:51:45 -0700824 log_warn("sync pattern reset sys:%u fpts:%u",
Song Zhao52f55192021-05-06 10:52:21 -0700825 systime, fpts);
826 }
827
Song Zhaoc03ba122020-12-23 21:54:02 -0800828 expire = (int)(systime - fpts) >= 0;
829
830 /* scatter the frame in different vsync whenever possible */
831 if (expire && next_frame && next_frame->pts && toggle_cnt) {
832 /* multi frame expired in current vsync but no frame in next vsync */
Song Zhaoea5a0412021-01-18 16:40:08 -0800833 if (systime + interval < next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800834 expire = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800835 log_debug("[%d]unset expire systime:%d inter:%d next_pts:%d toggle_cnt:%d",
836 avsync->session_id, systime, interval, next_frame->pts, toggle_cnt);
Song Zhaoc03ba122020-12-23 21:54:02 -0800837 }
838 } else if (!expire && next_frame && next_frame->pts && !toggle_cnt
839 && avsync->first_frame_toggled) {
840 /* next vsync will have at least 2 frame expired */
Song Zhao35a82df2021-04-15 10:58:49 -0700841 if (systime + interval >= next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800842 expire = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800843 log_debug("[%d]set expire systime:%d inter:%d next_pts:%d",
844 avsync->session_id, systime, interval, next_frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800845 }
846 }
847
Song Zhaoa58c3e92021-03-09 18:52:55 -0800848 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP)
849 correct_pattern(avsync->pattern_detector, frame, next_frame,
850 (avsync->last_frame?avsync->last_frame->hold_period:0),
851 avsync->last_holding_peroid, systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800852 interval, &expire);
Song Zhaoc03ba122020-12-23 21:54:02 -0800853
854 if (expire) {
855 avsync->vpts = fpts;
856 /* phase adjustment */
857 if (!avsync->phase_set) {
yongchun.lia50b1e92021-08-07 01:11:54 +0000858 //always adjust to the half v-sync to give most pts tolerace and unify behavior
859 if ((int)(systime - fpts) >= 0 && (int)(fpts + interval - systime) > 0) {
860 avsync->phase = interval/2 + fpts - systime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800861 avsync->phase_set = true;
yongchun.lia50b1e92021-08-07 01:11:54 +0000862 log_info("[%d]adjust phase to %d", avsync->session_id, (int)avsync->phase);
Song Zhaoc03ba122020-12-23 21:54:02 -0800863 }
864 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800865 if (avsync->state != AV_SYNC_STAT_SYNC_SETUP)
Song Zhaoea5a0412021-01-18 16:40:08 -0800866 log_info("[%d]sync setup", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800867 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhao5d2b4772021-01-18 16:40:08 -0800868 avsync->sync_lost_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800869 }
870 return expire;
871}
872
Song Zhao35a82df2021-04-15 10:58:49 -0700873static bool pattern_detect(struct av_sync_session* avsync, int cur_period, int last_period)
Song Zhaoc03ba122020-12-23 21:54:02 -0800874{
Song Zhao35a82df2021-04-15 10:58:49 -0700875 bool ret = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800876 log_trace("[%d]cur_period: %d last_period: %d",
877 avsync->session_id, cur_period, last_period);
Song Zhao35a82df2021-04-15 10:58:49 -0700878 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P32, cur_period, last_period))
879 ret = true;
880 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P22, cur_period, last_period))
881 ret = true;
882 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P41, cur_period, last_period))
883 ret = true;
884 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P11, cur_period, last_period))
885 ret = true;
886
887 return ret;
Song Zhaoc03ba122020-12-23 21:54:02 -0800888}
889
890int av_sync_set_speed(void *sync, float speed)
891{
892 struct av_sync_session *avsync = (struct av_sync_session *)sync;
893
894 if (speed < 0.001f || speed > 100) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800895 log_error("[%d]wrong speed %f [0.0001, 100]", avsync->session_id, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -0800896 return -1;
897 }
898
Song Zhaoea5a0412021-01-18 16:40:08 -0800899 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER ||
900 avsync->mode == AV_SYNC_MODE_IPTV) {
901 log_info("[%d]ignore set speed in mode %d", avsync->session_id, avsync->mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800902 return 0;
Song Zhaoea5a0412021-01-18 16:40:08 -0800903 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800904
Song Zhaoea5a0412021-01-18 16:40:08 -0800905 avsync->speed = speed;
906
907 if (avsync->type == AV_SYNC_TYPE_AUDIO) {
908 if (speed == 1.0) {
909 avsync->mode = avsync->backup_mode;
910 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
911 } else {
912 avsync->backup_mode = avsync->mode;
913 avsync->mode = AV_SYNC_MODE_FREE_RUN;
914 log_info("[%d]audio to freerun mode", avsync->session_id);
915 }
916 }
917#if 0
Song Zhaoc03ba122020-12-23 21:54:02 -0800918 if (avsync->mode != AV_SYNC_MODE_VMASTER) {
919 log_info("ignore set speed in mode %d", avsync->mode);
920 return 0;
921 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800922#endif
Song Zhaoc03ba122020-12-23 21:54:02 -0800923
Song Zhaoea5a0412021-01-18 16:40:08 -0800924 log_info("session[%d] set rate to %f", avsync->session_id, speed);
925 return msync_session_set_rate(avsync->fd, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -0800926}
927
928int av_sync_change_mode(void *sync, enum sync_mode mode)
929{
930 struct av_sync_session *avsync = (struct av_sync_session *)sync;
931
932 if (!avsync)
933 return -1;
934
Song Zhaoea5a0412021-01-18 16:40:08 -0800935 if (msync_session_set_mode(avsync->fd, mode)) {
936 log_error("[%d]fail to set mode %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800937 return -1;
938 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800939 avsync->mode = mode;
Song Zhaoea5a0412021-01-18 16:40:08 -0800940 log_info("[%d]update sync mode to %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800941 return 0;
942}
943
Song Zhao01031bb2021-05-13 21:23:20 -0700944int av_sync_get_mode(void *sync, enum sync_mode *mode)
945{
946 struct av_sync_session *avsync = (struct av_sync_session *)sync;
947
948 if (!avsync || !mode)
949 return -1;
950
951 *mode = avsync->mode;
952 return 0;
953}
954
Song Zhaoc03ba122020-12-23 21:54:02 -0800955int av_sync_set_pause_pts(void *sync, pts90K pts)
956{
957 struct av_sync_session *avsync = (struct av_sync_session *)sync;
958
959 if (!avsync)
960 return -1;
961
962 avsync->pause_pts = pts;
Song Zhaoea5a0412021-01-18 16:40:08 -0800963 log_info("[%d]set pause pts: %u", avsync->session_id, pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800964 return 0;
965}
966
967int av_sync_set_pause_pts_cb(void *sync, pause_pts_done cb, void *priv)
968{
969 struct av_sync_session *avsync = (struct av_sync_session *)sync;
970
971 if (!avsync)
972 return -1;
973
974 avsync->pause_pts_cb = cb;
975 avsync->pause_cb_priv = priv;
976 return 0;
977}
Song Zhaoea5a0412021-01-18 16:40:08 -0800978
979static void trigger_audio_start_cb(struct av_sync_session *avsync,
980 avs_ascb_reason reason)
981{
982 if (avsync) {
983 pthread_mutex_lock(&avsync->lock);
984 if (avsync->audio_start) {
985 avsync->audio_start(avsync->audio_start_priv, reason);
986 avsync->session_started = true;
987 avsync->audio_start = NULL;
988 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
989 }
990 pthread_mutex_unlock(&avsync->lock);
991 }
992}
993
994avs_start_ret av_sync_audio_start(
995 void *sync,
996 pts90K pts,
997 pts90K delay,
998 audio_start_cb cb,
999 void *priv)
1000{
1001 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1002 uint32_t start_mode;
yongchun.li59e873d2021-07-07 11:42:38 -07001003 uint32_t systime;
Song Zhaoea5a0412021-01-18 16:40:08 -08001004 avs_start_ret ret = AV_SYNC_ASTART_ERR;
1005 bool create_poll_t = false;
1006
1007 if (!avsync)
1008 return ret;
1009
yongchun.li59e873d2021-07-07 11:42:38 -07001010 log_info("%d av_sync_audio_start pts(ms) %d delay %d ms",
1011 avsync->session_id, (int)pts/90, (int)delay/90);
Song Zhaoea5a0412021-01-18 16:40:08 -08001012
yongchun.li59e873d2021-07-07 11:42:38 -07001013 if (avsync->in_audio_switch &&
1014 avsync->audio_switch_state == AUDIO_SWITCH_STAT_AGAIN)
1015 {
1016 start_mode = AVS_START_SYNC;
1017 log_info("%d AUDIO_SWITCH_STAT_AGAIN", avsync->session_id);
1018 } else {
1019 if (msync_session_set_audio_start(avsync->fd, pts, delay, &start_mode))
1020 log_error("[%d]fail to set audio start", avsync->session_id);
1021 }
1022 if (avsync->in_audio_switch &&
1023 (avsync->audio_switch_state == AUDIO_SWITCH_STAT_RESET ||
1024 avsync->audio_switch_state == AUDIO_SWITCH_STAT_AGAIN)) {
1025 msync_session_get_wall(avsync->fd, &systime, NULL);
1026 if ((int)(systime - pts) > A_ADJ_THREDHOLD_LB &&
1027 start_mode == AVS_START_SYNC) {
1028 log_info("%d audio_switch audio need drop first.ahead %d ms",
1029 avsync->session_id, (int)(systime - pts)/90);
1030 ret = AV_SYNC_ASTART_AGAIN;
1031 avsync->audio_switch_state = AUDIO_SWITCH_STAT_AGAIN;
1032 goto exit;
1033 }
1034 else {
1035 int diff = (int)(pts - systime);
1036 log_info("%d audio_switch_state to start mode %d diff %d ms",
1037 avsync->session_id, start_mode, diff/90);
1038 avsync->audio_switch_state = AUDIO_SWITCH_STAT_START;
1039 if (diff < A_ADJ_THREDHOLD_LB) {
1040 log_info("%d orig mode %d already close enough direct start",
1041 avsync->session_id, start_mode);
1042 start_mode = AVS_START_SYNC;
1043 }
1044 }
yongchun.li107a6162021-05-05 02:38:57 -07001045 }
1046
Song Zhaoea5a0412021-01-18 16:40:08 -08001047 if (start_mode == AVS_START_SYNC) {
1048 ret = AV_SYNC_ASTART_SYNC;
1049 avsync->session_started = true;
Song Zhao065800e2021-05-26 15:56:06 -07001050 avsync->state = AV_SYNC_STAT_RUNNING;
Song Zhaod62bb392021-04-23 12:25:49 -07001051 } else if (start_mode == AVS_START_ASYNC) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001052 ret = AV_SYNC_ASTART_ASYNC;
Song Zhaod62bb392021-04-23 12:25:49 -07001053 avsync->state = AV_SYNC_STAT_RUNNING;
1054 } else if (start_mode == AVS_START_AGAIN) {
1055 ret = AV_SYNC_ASTART_AGAIN;
1056 }
1057
1058 if (ret == AV_SYNC_ASTART_AGAIN)
1059 goto exit;
Song Zhaoea5a0412021-01-18 16:40:08 -08001060
yongchun.li107a6162021-05-05 02:38:57 -07001061 if (avsync->mode == AV_SYNC_MODE_AMASTER || avsync->in_audio_switch) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001062 create_poll_t = true;
1063 if (start_mode == AVS_START_ASYNC) {
1064 if (!cb) {
1065 log_error("[%d]invalid cb", avsync->session_id);
1066 return AV_SYNC_ASTART_ERR;
1067 }
1068 avsync->audio_start = cb;
1069 avsync->audio_start_priv = priv;
1070 }
Song Zhaod62bb392021-04-23 12:25:49 -07001071 } else if (LIVE_MODE(avsync->mode))
Song Zhaoea5a0412021-01-18 16:40:08 -08001072 create_poll_t = true;
1073
Song Zhaod62bb392021-04-23 12:25:49 -07001074 if (create_poll_t && !avsync->poll_thread) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001075 int ret;
1076
1077 log_info("[%d]start poll thread", avsync->session_id);
1078 avsync->quit_poll = false;
1079 ret = pthread_create(&avsync->poll_thread, NULL, poll_thread, avsync);
1080 if (ret) {
1081 log_error("[%d]create poll thread errno %d", avsync->session_id, errno);
1082 return AV_SYNC_ASTART_ERR;
1083 }
1084 }
Song Zhaod62bb392021-04-23 12:25:49 -07001085 if (LIVE_MODE(avsync->mode)) {
Song Zhaod62bb392021-04-23 12:25:49 -07001086 msync_session_get_wall(avsync->fd, &systime, NULL);
1087 log_info("[%d]return %u w %u pts %u d %u",
1088 avsync->session_id, ret, systime, pts, delay);
1089 }
1090exit:
Song Zhaoea5a0412021-01-18 16:40:08 -08001091 log_info("[%d]return %u", avsync->session_id, ret);
1092 return ret;
1093}
1094
1095int av_sync_audio_render(
1096 void *sync,
1097 pts90K pts,
1098 struct audio_policy *policy)
1099{
1100 int ret = 0;
Song Zhao065800e2021-05-26 15:56:06 -07001101 bool out_lier = false;
Song Zhaoea5a0412021-01-18 16:40:08 -08001102 uint32_t systime;
1103 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1104 avs_audio_action action = AA_SYNC_AA_MAX;
1105
1106 if (!avsync || !policy)
1107 return -1;
1108
yongchun.li107a6162021-05-05 02:38:57 -07001109 msync_session_get_wall(avsync->fd, &systime, NULL);
1110
1111 log_trace("audio render pts %u, systime %u, mode %u diff ms %d",
1112 pts, systime, avsync->mode, (int)(pts-systime)/90);
1113
1114 if (avsync->in_audio_switch
1115 && avsync->audio_switch_state == AUDIO_SWITCH_STAT_START) {
1116 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_HB) {
1117 log_info("Audio pts in system range sys %u pts %u\n", systime, pts);
1118 avsync->audio_switch_state = AUDIO_SWITCH_STAT_FINISH;
1119 action = AV_SYNC_AA_RENDER;
1120 } else if ((int)(systime - pts) > 0) {
1121 log_info("[%d] audio change drop %d ms sys %u pts %u", avsync->session_id,
1122 (int)(systime - pts)/90, systime, pts);
1123 action = AV_SYNC_AA_DROP;
1124 } else {
1125 action = AV_SYNC_AA_INSERT;
1126 log_info("[%d] audio change insert %d ms sys %u pts %u", avsync->session_id,
1127 (int)(pts - systime)/90, systime, pts);
1128 }
1129 goto done;
1130 }
1131
Song Zhaoea5a0412021-01-18 16:40:08 -08001132 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
1133 avsync->mode == AV_SYNC_MODE_AMASTER) {
1134 action = AV_SYNC_AA_RENDER;
1135 goto done;
1136 }
1137
Song Zhaod62bb392021-04-23 12:25:49 -07001138 /* stopping procedure, unblock audio rendering */
1139 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER &&
1140 avsync->active_mode == AV_SYNC_MODE_FREE_RUN) {
1141 action = AV_SYNC_AA_DROP;
1142 goto done;
1143 }
1144
Song Zhao7daf3a12021-05-10 22:22:25 -07001145 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
1146 avsync->mode == AV_SYNC_MODE_AMASTER) {
1147 action = AV_SYNC_AA_RENDER;
1148 goto done;
1149 }
1150
Song Zhaod62bb392021-04-23 12:25:49 -07001151 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP &&
1152 LIVE_MODE(avsync->mode) &&
1153 abs_diff(systime, pts) > STREAM_DISC_THRES) {
1154 /* outlier by stream error */
1155 avsync->outlier_cnt++;
1156 if (avsync->outlier_cnt > OUTLIER_MAX_CNT) {
1157 /* treat as disc, just drop current frame */
1158 avsync->state = AV_SYNC_STAT_SYNC_LOST;
1159 avsync->outlier_cnt = 0;
1160 action = AV_SYNC_AA_DROP;
1161 systime = pts;
Song Zhaod62bb392021-04-23 12:25:49 -07001162 goto done;
1163 }
1164 log_info("[%d]ignore outlier %u", avsync->session_id, pts);
1165 pts = systime;
1166 action = AV_SYNC_AA_RENDER;
Song Zhao065800e2021-05-26 15:56:06 -07001167 out_lier = true;
Song Zhaod62bb392021-04-23 12:25:49 -07001168 goto done;
1169 }
1170
1171 avsync->outlier_cnt = 0;
1172 /* low bound from sync_lost to sync_setup */
1173 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_LB) {
1174 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
1175 action = AV_SYNC_AA_RENDER;
1176 goto done;
1177 }
1178
1179 /* high bound of sync_setup */
1180 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_HB &&
1181 avsync->state != AV_SYNC_STAT_SYNC_LOST) {
1182 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhaoea5a0412021-01-18 16:40:08 -08001183 action = AV_SYNC_AA_RENDER;
1184 goto done;
1185 }
1186
1187 if ((int)(systime - pts) > 0) {
Song Zhaod62bb392021-04-23 12:25:49 -07001188 avsync->state = AV_SYNC_STAT_SYNC_LOST;
Song Zhaoea5a0412021-01-18 16:40:08 -08001189 action = AV_SYNC_AA_DROP;
1190 goto done;
1191 }
1192
1193 if ((int)(systime - pts) < 0) {
Song Zhaod62bb392021-04-23 12:25:49 -07001194 avsync->state = AV_SYNC_STAT_SYNC_LOST;
Song Zhaoea5a0412021-01-18 16:40:08 -08001195 action = AV_SYNC_AA_INSERT;
1196 goto done;
1197 }
1198
1199done:
1200 policy->action = action;
1201 policy->delta = (int)(systime - pts);
1202 if (action == AV_SYNC_AA_RENDER) {
1203 avsync->apts = pts;
yongchun.li107a6162021-05-05 02:38:57 -07001204 if (!avsync->in_audio_switch) {
Song Zhao065800e2021-05-26 15:56:06 -07001205 if (!out_lier)
1206 msync_session_update_apts(avsync->fd, systime, pts, 0);
Song Zhaof46932e2021-05-21 01:51:45 -07001207 log_debug("[%d]return %d sys %u - pts %u = %d",
Song Zhao409739b2021-05-12 22:21:40 -07001208 avsync->session_id, action, systime, pts, systime - pts);
yongchun.li107a6162021-05-05 02:38:57 -07001209 } else if(avsync->audio_switch_state == AUDIO_SWITCH_STAT_FINISH) {
1210 msync_session_update_apts(avsync->fd, systime, pts, 0);
1211 log_info("[%d] audio switch done sys %u pts %u",
1212 avsync->session_id, systime, pts);
1213 msync_session_set_audio_switch(avsync->fd, false);
1214 avsync->in_audio_switch = false;
1215 avsync->audio_switch_state = AUDIO_SWITCH_STAT_INIT;
1216 } else {
1217 log_trace("[%d] in audio switch ret %d sys %u - pts %u = %d",
1218 avsync->session_id, action, systime, pts, systime - pts);
1219 }
Song Zhaoa2985cb2021-06-24 12:01:47 -07001220 avsync->audio_drop_cnt = 0;
Song Zhaoea5a0412021-01-18 16:40:08 -08001221 } else {
Song Zhaoa2985cb2021-06-24 12:01:47 -07001222 if (abs_diff(systime, pts) > avsync->disc_thres_min &&
yongchun.li085b5a42021-05-24 04:22:53 -07001223 avsync->last_disc_pts != pts &&
1224 !avsync->in_audio_switch) {
Song Zhao409739b2021-05-12 22:21:40 -07001225 log_info ("[%d]audio disc %u --> %u",
1226 avsync->session_id, systime, pts);
1227 msync_session_set_audio_dis(avsync->fd, pts);
1228 avsync->last_disc_pts = pts;
Song Zhaoa2985cb2021-06-24 12:01:47 -07001229 } else if (action == AV_SYNC_AA_DROP) {
yongchun.li0ee6e372021-08-20 04:26:04 -07001230 struct timespec now;
Song Zhaoa2985cb2021-06-24 12:01:47 -07001231
1232 /* dropping recovery */
yongchun.li0ee6e372021-08-20 04:26:04 -07001233 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
Song Zhaoa2985cb2021-06-24 12:01:47 -07001234 if (!avsync->audio_drop_cnt)
1235 avsync->audio_drop_start = now;
1236 avsync->audio_drop_cnt++;
1237 if (time_diff(&now, &avsync->audio_drop_start) > 500000) {
1238 log_info ("[%d]audio keep dropping sys %u vs a %u",
1239 avsync->session_id, systime, pts);
1240 msync_session_set_audio_dis(avsync->fd, pts);
1241 }
Song Zhao409739b2021-05-12 22:21:40 -07001242 }
Song Zhaoa2985cb2021-06-24 12:01:47 -07001243 if (action != AV_SYNC_AA_DROP)
1244 avsync->audio_drop_cnt = 0;
Song Zhaof46932e2021-05-21 01:51:45 -07001245 log_debug("[%d]return %d sys %u - pts %u = %d",
Song Zhaod62bb392021-04-23 12:25:49 -07001246 avsync->session_id, action, systime, pts, systime - pts);
Song Zhaoea5a0412021-01-18 16:40:08 -08001247 }
1248
1249 return ret;
1250}
1251
1252int av_sync_get_clock(void *sync, pts90K *pts)
1253{
1254 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1255
1256 if (!avsync || !pts)
1257 return -1;
1258 return msync_session_get_wall(avsync->fd, pts, NULL);
1259}
1260
1261static void handle_mode_change_a(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -07001262 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -08001263{
bo.xiao1f94b352021-08-02 03:53:47 -04001264 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 -07001265 avsync->active_mode, avsync->mode, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -08001266 if (avsync->active_mode == AV_SYNC_MODE_AMASTER) {
1267 float speed;
1268 if (avsync->start_policy == AV_SYNC_START_ALIGN &&
Song Zhaoe208d692021-04-19 15:38:52 -07001269 a_active && avsync->audio_start) {
yongchun.li107a6162021-05-05 02:38:57 -07001270 if (v_active || v_timeout || avsync->in_audio_switch) {
Song Zhaoe208d692021-04-19 15:38:52 -07001271 log_info("audio start cb");
1272 trigger_audio_start_cb(avsync, AV_SYNC_ASCB_OK);
yongchun.li107a6162021-05-05 02:38:57 -07001273 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001274 }
1275
1276 if (!msync_session_get_rate(avsync->fd, &speed)) {
1277 /* speed change is triggered by asink,
1278 * attached audio HAL will handle it
1279 */
1280 if (speed != avsync->speed)
1281 log_info("[%d]new rate %f", avsync->session_id, speed);
1282 if (speed == 1.0) {
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001283 if (avsync->mode != avsync->backup_mode) {
1284 avsync->mode = avsync->backup_mode;
1285 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
1286 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001287 } else {
1288 avsync->backup_mode = avsync->mode;
1289 avsync->mode = AV_SYNC_MODE_FREE_RUN;
1290 log_info("[%d]audio to freerun mode", avsync->session_id);
1291 }
1292 avsync->speed = speed;
1293 }
Song Zhaod62bb392021-04-23 12:25:49 -07001294 } else if (avsync->active_mode == AV_SYNC_MODE_PCR_MASTER) {
1295 struct session_debug debug;
1296 if (!msync_session_get_debug_mode(avsync->fd, &debug)) {
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001297 if (debug.debug_freerun && !avsync->debug_freerun) {
Song Zhaod62bb392021-04-23 12:25:49 -07001298 avsync->backup_mode = avsync->mode;
1299 avsync->mode = AV_SYNC_MODE_FREE_RUN;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001300 avsync->debug_freerun = true;
Song Zhaod62bb392021-04-23 12:25:49 -07001301 log_warn("[%d]audio to freerun mode", avsync->session_id);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001302 } else if (!debug.debug_freerun && avsync->debug_freerun) {
Song Zhaod62bb392021-04-23 12:25:49 -07001303 avsync->mode = avsync->backup_mode;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001304 avsync->debug_freerun = false;
Song Zhaod62bb392021-04-23 12:25:49 -07001305 log_warn("[%d]audio back to mode %d",
1306 avsync->session_id, avsync->mode);
1307 }
1308 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001309 }
1310}
1311
1312static void handle_mode_change_v(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -07001313 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -08001314{
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001315 struct session_debug debug;
1316
bo.xiao1f94b352021-08-02 03:53:47 -04001317 log_info("[%d]av_sync amode mode %d %d v/a %d/%d", avsync->session_id,
Song Zhaoea5a0412021-01-18 16:40:08 -08001318 avsync->active_mode, avsync->mode, v_active, a_active);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001319 if (!msync_session_get_debug_mode(avsync->fd, &debug)) {
1320 if (debug.debug_freerun && !avsync->debug_freerun) {
1321 avsync->backup_mode = avsync->mode;
1322 avsync->mode = AV_SYNC_MODE_FREE_RUN;
1323 avsync->debug_freerun = true;
1324 log_warn("[%d]video to freerun mode", avsync->session_id);
1325 } else if (!debug.debug_freerun && avsync->debug_freerun) {
1326 avsync->mode = avsync->backup_mode;
1327 avsync->debug_freerun = false;
1328 log_warn("[%d]video back to mode %d",
1329 avsync->session_id, avsync->mode);
Song Zhaod62bb392021-04-23 12:25:49 -07001330 }
1331 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001332}
1333
1334static void * poll_thread(void * arg)
1335{
1336 int ret = 0;
1337 struct av_sync_session *avsync = (struct av_sync_session *)arg;
1338 const int fd = avsync->fd;
1339 struct pollfd pfd = {
1340 /* default blocking capture */
1341 .events = POLLIN | POLLRDNORM | POLLPRI | POLLOUT | POLLWRNORM,
1342 .fd = avsync->fd,
1343 };
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001344 enum src_flag sflag = SRC_A;
Song Zhaoea5a0412021-01-18 16:40:08 -08001345
1346 prctl (PR_SET_NAME, "avs_poll");
1347 log_info("[%d]enter", avsync->session_id);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001348
1349 if (avsync->type == AV_SYNC_TYPE_AUDIO)
1350 sflag = SRC_A;
1351 else if (avsync->type == AV_SYNC_TYPE_VIDEO)
1352 sflag = SRC_V;
1353
Song Zhaoea5a0412021-01-18 16:40:08 -08001354 while (!avsync->quit_poll) {
1355 for (;;) {
1356 ret = poll(&pfd, 1, 10);
1357 if (ret > 0)
1358 break;
1359 if (avsync->quit_poll)
1360 goto exit;
1361 if (errno == EINTR)
1362 continue;
1363 }
1364
1365 /* error handling */
1366 if (pfd.revents & POLLERR)
1367 log_error("[%d]POLLERR received", avsync->session_id);
1368
Song Zhaod62bb392021-04-23 12:25:49 -07001369 /* mode change. Non-exclusive wait so all the processes
1370 * shall be woken up
1371 */
Song Zhaoea5a0412021-01-18 16:40:08 -08001372 if (pfd.revents & POLLPRI) {
Song Zhaoe208d692021-04-19 15:38:52 -07001373 bool v_active, a_active, v_timeout;
Song Zhaoea5a0412021-01-18 16:40:08 -08001374
1375 msync_session_get_stat(fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001376 &v_active, &a_active, &v_timeout, &avsync->in_audio_switch, sflag);
Song Zhaoea5a0412021-01-18 16:40:08 -08001377
1378 if (avsync->type == AV_SYNC_TYPE_AUDIO)
Song Zhaoe208d692021-04-19 15:38:52 -07001379 handle_mode_change_a(avsync, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -08001380 else if (avsync->type == AV_SYNC_TYPE_VIDEO)
Song Zhaoe208d692021-04-19 15:38:52 -07001381 handle_mode_change_v(avsync, v_active, a_active, v_timeout);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001382 usleep(10000);
Song Zhaoea5a0412021-01-18 16:40:08 -08001383 }
1384 }
1385exit:
1386 log_info("[%d]quit", avsync->session_id);
1387 return NULL;
1388}
1389
Song Zhaod62bb392021-04-23 12:25:49 -07001390int av_sync_set_pcr_clock(void *sync, pts90K pts, uint64_t mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -08001391{
1392 struct av_sync_session *avsync = (struct av_sync_session *)sync;
wei.dubcc2ed22021-05-19 07:16:10 -04001393 struct pcr_info pcr;
1394 enum pcr_monitor_status status;
1395 int ppm;
Song Zhaoea5a0412021-01-18 16:40:08 -08001396 if (!avsync)
1397 return -1;
1398
1399 if (avsync->type != AV_SYNC_TYPE_PCR)
1400 return -2;
1401
wei.dubcc2ed22021-05-19 07:16:10 -04001402 pcr.monoclk = mono_clock / 1000;
1403 pcr.pts = (long long) pts * 1000 / 90;
1404 pcr_monitor_process(avsync->pcr_monitor, &pcr);
1405
1406 status = pcr_monitor_get_status(avsync->pcr_monitor);
1407
1408 if (status >= DEVIATION_READY) {
1409 pcr_monitor_get_deviation(avsync->pcr_monitor, &ppm);
1410 if (avsync->ppm != ppm) {
1411 avsync->ppm = ppm;
1412 log_info("[%d]ppm:%d", avsync->session_id, ppm);
1413 if (msync_session_set_clock_dev(avsync->fd, ppm))
1414 log_error("set clock dev fail");
1415 }
1416 }
1417
Song Zhaod62bb392021-04-23 12:25:49 -07001418 return msync_session_set_pcr(avsync->fd, pts, mono_clock);
Song Zhaoea5a0412021-01-18 16:40:08 -08001419}
1420
Song Zhaod62bb392021-04-23 12:25:49 -07001421int av_sync_get_pcr_clock(void *sync, pts90K *pts, uint64_t * mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -08001422{
1423 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1424
1425 if (!avsync)
1426 return -1;
1427
Song Zhaod62bb392021-04-23 12:25:49 -07001428 return msync_session_get_pcr(avsync->fd, pts, mono_clock);
Song Zhaoea5a0412021-01-18 16:40:08 -08001429}
1430
1431int av_sync_set_session_name(void *sync, const char *name)
1432{
1433 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1434
1435 if (!avsync)
1436 return -1;
1437
1438 return msync_session_set_name(avsync->fd, name);
1439}
yongchun.li107a6162021-05-05 02:38:57 -07001440
1441int av_sync_set_audio_switch(void *sync, bool start)
1442{
1443 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1444 bool v_active, a_active, v_timeout;
1445
1446 if (!avsync)
1447 return -1;
1448 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
1449 &v_active, &a_active,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001450 &v_timeout, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -07001451 log_error("[%d] can not get session state",
1452 avsync->session_id);
1453 return -1;
1454 }
1455 if (!v_active || !a_active) {
1456 log_error("[%d] no apply if not AV both active v %d a %d",
1457 avsync->session_id, v_active, a_active);
1458 return -1;
1459 }
1460 if (msync_session_set_audio_switch(avsync->fd, start)) {
1461 log_error("[%d]fail to set audio switch %d", avsync->session_id, start);
1462 return -1;
1463 }
1464 avsync->in_audio_switch = start;
1465 avsync->audio_switch_state = AUDIO_SWITCH_STAT_INIT;
1466 log_info("[%d]update audio switch to %d", avsync->session_id, start);
1467 return 0;
1468}
1469
1470int av_sync_get_audio_switch(void *sync, bool *start)
1471{
1472 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1473
1474 if (!avsync)
1475 return -1;
1476 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001477 NULL, NULL, NULL, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -07001478 log_error("[%d] can not audio seamless switch state",
1479 avsync->session_id);
1480 return -1;
1481 }
1482 if (start) *start = avsync->in_audio_switch;
1483 return 0;
Song Zhao7daf3a12021-05-10 22:22:25 -07001484}
Song Zhao8039f562021-05-18 18:11:25 -07001485
1486enum clock_recovery_stat av_sync_get_clock_devication(void *sync, int32_t *ppm)
1487{
1488 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1489
wei.dubcc2ed22021-05-19 07:16:10 -04001490 if (!avsync || !ppm)
1491 return CLK_RECOVERY_ERR;
1492 if (avsync->mode != AV_SYNC_MODE_PCR_MASTER)
Song Zhao8039f562021-05-18 18:11:25 -07001493 return CLK_RECOVERY_NOT_RUNNING;
1494
wei.dubcc2ed22021-05-19 07:16:10 -04001495 if (msync_session_get_clock_dev(avsync->fd, ppm))
1496 return CLK_RECOVERY_ERR;
1497
1498 if (*ppm == 0)
1499 return CLK_RECOVERY_ONGOING;
1500 else
1501 return CLK_RECOVERY_READY;
Song Zhao8039f562021-05-18 18:11:25 -07001502}