blob: 10c1193e4cd7c53acae116a779a9474dd5bbeb75 [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;
479 struct vframe *prev;
480 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);
516 prev->free(prev);
Song Zhaoea5a0412021-01-18 16:40:08 -0800517 log_info ("[%d]drop frame with same pts %u", avsync->session_id, frame->pts);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700518 } else if (avsync->fps_cnt < 100) {
519 int32_t interval = frame->pts - avsync->last_q_pts;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700520
521 if (interval > 0 && interval <= 4500) {
522 if (avsync->fps_interval_acc == -1) {
523 avsync->fps_interval_acc = interval;
524 avsync->fps_cnt = 1;
525 } else {
526 avsync->fps_interval_acc += interval;
527 avsync->fps_cnt++;
528 avsync->fps_interval = avsync->fps_interval_acc / avsync->fps_cnt;
529 if (avsync->fps_cnt == 100)
530 log_info("[%d] fps_interval = %d", avsync->session_id, avsync->fps_interval);
531 }
532 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800533 }
534 }
535
Song Zhao065800e2021-05-26 15:56:06 -0700536 if (frame->duration == -1)
537 frame->duration = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800538 frame->hold_period = 0;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700539 avsync->last_q_pts = frame->pts;
Song Zhaoc03ba122020-12-23 21:54:02 -0800540 ret = queue_item(avsync->frame_q, frame);
541 if (avsync->state == AV_SYNC_STAT_INIT &&
542 queue_size(avsync->frame_q) >= avsync->start_thres) {
543 avsync->state = AV_SYNC_STAT_RUNNING;
Song Zhaoea5a0412021-01-18 16:40:08 -0800544 log_info("[%d]state: init --> running", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800545 }
546
547 if (ret)
548 log_error("%s queue fail:%d", ret);
Song Zhaoea5a0412021-01-18 16:40:08 -0800549 log_debug("[%d]push %u", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800550 return ret;
551
552}
553
554struct vframe *av_sync_pop_frame(void *sync)
555{
Song Zhaoea5a0412021-01-18 16:40:08 -0800556 struct vframe *frame = NULL, *enter_last_frame = NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800557 struct av_sync_session *avsync = (struct av_sync_session *)sync;
558 int toggle_cnt = 0;
559 uint32_t systime;
Song Zhao468fd652021-01-15 22:13:04 -0800560 bool pause_pts_reached = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800561 uint32_t interval;
Song Zhaoc03ba122020-12-23 21:54:02 -0800562
563 pthread_mutex_lock(&avsync->lock);
564 if (avsync->state == AV_SYNC_STAT_INIT) {
Song Zhaod62bb392021-04-23 12:25:49 -0700565 log_info("[%d]in state INIT", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800566 goto exit;
567 }
568
Song Zhaoea5a0412021-01-18 16:40:08 -0800569 if (!avsync->session_started) {
Song Zhao35a82df2021-04-15 10:58:49 -0700570 uint32_t pts;
571
Song Zhaoc03ba122020-12-23 21:54:02 -0800572 if (peek_item(avsync->frame_q, (void **)&frame, 0) || !frame) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800573 log_info("[%d]empty q", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800574 goto exit;
575 }
Song Zhao35a82df2021-04-15 10:58:49 -0700576 msync_session_get_wall(avsync->fd, &systime, &interval);
577 pts = frame->pts - avsync->delay * interval;
578 msync_session_set_video_start(avsync->fd, pts);
Song Zhaoea5a0412021-01-18 16:40:08 -0800579 avsync->session_started = true;
Song Zhao35a82df2021-04-15 10:58:49 -0700580 log_info("[%d]video start %u", avsync->session_id, pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800581 }
582
Song Zhaoea5a0412021-01-18 16:40:08 -0800583 if (avsync->start_policy == AV_SYNC_START_ALIGN &&
Song Zhaod4109b62021-04-30 08:47:17 -0700584 !avsync->first_frame_toggled &&
585 !msync_clock_started(avsync->fd)) {
586 pthread_mutex_unlock(&avsync->lock);
Song Zhaoea5a0412021-01-18 16:40:08 -0800587 log_trace("[%d]clock not started", avsync->session_id);
588 return NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800589 }
590
Song Zhaoea5a0412021-01-18 16:40:08 -0800591 enter_last_frame = avsync->last_frame;
592 msync_session_get_wall(avsync->fd, &systime, &interval);
593
594 /* handle refresh rate change */
595 if (avsync->vsync_interval == AV_SYNC_INVALID_PAUSE_PTS ||
596 avsync->vsync_interval != interval) {
597 log_info("[%d]vsync interval update %d --> %u",
598 avsync->session_id, avsync->vsync_interval, interval);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700599 if (avsync->fps_interval == -1)
600 avsync->fps_interval = interval;
Song Zhaoea5a0412021-01-18 16:40:08 -0800601 avsync->vsync_interval = interval;
602 avsync->phase_set = false;
Song Zhaode5f73b2021-07-23 22:38:07 -0700603 avsync->phase = 0;
Song Zhaoea5a0412021-01-18 16:40:08 -0800604 reset_pattern(avsync->pattern_detector);
605 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800606 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
607 struct vframe *next_frame = NULL;
608
609 peek_item(avsync->frame_q, (void **)&next_frame, 1);
610 if (next_frame)
Song Zhaof46932e2021-05-21 01:51:45 -0700611 log_debug("[%d]cur_f %u next_f %u size %d",
612 avsync->session_id, frame->pts, next_frame->pts, queue_size(avsync->frame_q));
Song Zhaoea5a0412021-01-18 16:40:08 -0800613 if (frame_expire(avsync, systime, interval,
614 frame, next_frame, toggle_cnt)) {
615 log_debug("[%d]cur_f %u expire", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800616 toggle_cnt++;
617
Song Zhao35a82df2021-04-15 10:58:49 -0700618 if (pattern_detect(avsync,
Song Zhaoc03ba122020-12-23 21:54:02 -0800619 (avsync->last_frame?avsync->last_frame->hold_period:0),
Song Zhao35a82df2021-04-15 10:58:49 -0700620 avsync->last_holding_peroid))
621 log_info("[%d] %u break the pattern", avsync->session_id, avsync->last_frame->pts);
622
Song Zhaoc03ba122020-12-23 21:54:02 -0800623 if (avsync->last_frame)
624 avsync->last_holding_peroid = avsync->last_frame->hold_period;
625
626 dqueue_item(avsync->frame_q, (void **)&frame);
627 if (avsync->last_frame) {
628 /* free frame that are not for display */
Song Zhaoea5a0412021-01-18 16:40:08 -0800629 if (toggle_cnt > 1) {
Song Zhao35a82df2021-04-15 10:58:49 -0700630 log_debug("[%d]free %u cur %u system/d %u/%u", avsync->session_id,
631 avsync->last_frame->pts, frame->pts, systime, systime - avsync->last_poptime);
Song Zhaoc03ba122020-12-23 21:54:02 -0800632 avsync->last_frame->free(avsync->last_frame);
Song Zhaoea5a0412021-01-18 16:40:08 -0800633 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800634 } else {
635 avsync->first_frame_toggled = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800636 log_info("[%d]first frame %u", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800637 }
638 avsync->last_frame = frame;
Song Zhao5d2b4772021-01-18 16:40:08 -0800639 avsync->last_pts = frame->pts;
Song Zhaoc03ba122020-12-23 21:54:02 -0800640 } else
641 break;
642 }
643
644 /* pause pts */
645 if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS && avsync->last_frame) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800646 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
Song Zhao468fd652021-01-15 22:13:04 -0800647 pause_pts_reached = true;
Song Zhaoc03ba122020-12-23 21:54:02 -0800648 else
Song Zhao468fd652021-01-15 22:13:04 -0800649 pause_pts_reached = (int)(avsync->last_frame->pts - avsync->pause_pts) >= 0;
650 } else if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS) {
651 if (!peek_item(avsync->frame_q, (void **)&frame, 0))
652 pause_pts_reached = (int)(frame->pts - avsync->pause_pts) >= 0;
653 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800654
Song Zhao468fd652021-01-15 22:13:04 -0800655 if (pause_pts_reached) {
656 if (avsync->pause_pts_cb)
657 avsync->pause_pts_cb(avsync->pause_pts,
Song Zhaoc03ba122020-12-23 21:54:02 -0800658 avsync->pause_cb_priv);
659
Song Zhao468fd652021-01-15 22:13:04 -0800660 /* stay in paused until av_sync_pause(false) */
661 avsync->paused = true;
662 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
Song Zhaoea5a0412021-01-18 16:40:08 -0800663 log_info ("[%d]reach pause pts: %u",
664 avsync->session_id, avsync->last_frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800665 }
666
667exit:
668 pthread_mutex_unlock(&avsync->lock);
669 if (avsync->last_frame) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800670 if (enter_last_frame != avsync->last_frame)
671 log_debug("[%d]pop %u", avsync->session_id, avsync->last_frame->pts);
Song Zhao35a82df2021-04-15 10:58:49 -0700672 log_trace("[%d]pop %u", avsync->session_id, avsync->last_frame->pts);
Song Zhao065800e2021-05-26 15:56:06 -0700673 /* don't update vpts for out_lier */
674 if (avsync->last_frame->duration != -1)
675 msync_session_update_vpts(avsync->fd, systime,
676 avsync->last_frame->pts, interval * avsync->delay);
Song Zhaoc03ba122020-12-23 21:54:02 -0800677 } else
Song Zhaoea5a0412021-01-18 16:40:08 -0800678 if (enter_last_frame != avsync->last_frame)
679 log_debug("[%d]pop (nil)", avsync->session_id);
680
Song Zhao35a82df2021-04-15 10:58:49 -0700681 avsync->last_poptime = systime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800682 if (avsync->last_frame)
683 avsync->last_frame->hold_period++;
684 return avsync->last_frame;
685}
686
Song Zhaoc03ba122020-12-23 21:54:02 -0800687static inline uint32_t abs_diff(uint32_t a, uint32_t b)
688{
Song Zhaoea5a0412021-01-18 16:40:08 -0800689 return (int)(a - b) > 0 ? a - b : b - a;
Song Zhaoc03ba122020-12-23 21:54:02 -0800690}
691
yongchun.li0ee6e372021-08-20 04:26:04 -0700692static uint64_t time_diff (struct timespec *b, struct timespec *a)
Song Zhaoc03ba122020-12-23 21:54:02 -0800693{
yongchun.li0ee6e372021-08-20 04:26:04 -0700694 return (b->tv_sec - a->tv_sec)*1000000 + (b->tv_nsec/1000 - a->tv_nsec/1000);
Song Zhaoc03ba122020-12-23 21:54:02 -0800695}
696
Song Zhaoc03ba122020-12-23 21:54:02 -0800697static bool frame_expire(struct av_sync_session* avsync,
698 uint32_t systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800699 uint32_t interval,
Song Zhaoc03ba122020-12-23 21:54:02 -0800700 struct vframe * frame,
701 struct vframe * next_frame,
702 int toggle_cnt)
703{
704 uint32_t fpts = frame->pts;
705 bool expire = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800706 uint32_t pts_correction = avsync->delay * interval;
Song Zhaoc03ba122020-12-23 21:54:02 -0800707
708 if (avsync->paused && avsync->pause_pts == AV_SYNC_INVALID_PAUSE_PTS)
709 return false;
710
711 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
712 return true;
713
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700714 if (avsync->mode == AV_SYNC_MODE_FREE_RUN) {
715 /* render according to FPS */
716 if (!VALID_TS(avsync->last_r_syst) ||
717 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
718 avsync->last_r_syst = systime;
719 return true;
720 }
721 return false;
722 }
723
Song Zhaoc03ba122020-12-23 21:54:02 -0800724 if (!fpts) {
725 if (avsync->last_frame) {
726 /* try to accumulate duration as PTS */
727 fpts = avsync->vpts + avsync->last_frame->duration;
728 } else {
729 fpts = avsync->vpts;
730 }
731 }
732 systime += pts_correction;
733
734 /* phase adjustment */
735 if (avsync->phase_set)
736 systime += avsync->phase;
737
yongchun.lia50b1e92021-08-07 01:11:54 +0000738 log_trace("[%d]systime:%u phase:%d correct:%u fpts:%u",
Song Zhaoea5a0412021-01-18 16:40:08 -0800739 avsync->session_id, systime,
yongchun.lia50b1e92021-08-07 01:11:54 +0000740 avsync->phase_set? (int)avsync->phase:0, pts_correction, fpts);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700741 if (abs_diff(systime, fpts) > avsync->disc_thres_min) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800742 /* ignore discontinity under pause */
Song Zhaoea5a0412021-01-18 16:40:08 -0800743 if (avsync->paused)
Song Zhaoc03ba122020-12-23 21:54:02 -0800744 return false;
745
Song Zhaoa2985cb2021-06-24 12:01:47 -0700746 if ((VALID_TS(avsync->last_log_syst) && avsync->last_log_syst != systime) ||
747 (VALID_TS(avsync->last_pts) && avsync->last_pts != fpts)) {
yongchun.li0ee6e372021-08-20 04:26:04 -0700748 struct timespec now;
Song Zhao5d2b4772021-01-18 16:40:08 -0800749
yongchun.li0ee6e372021-08-20 04:26:04 -0700750 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700751 avsync->last_log_syst = systime;
Song Zhao5d2b4772021-01-18 16:40:08 -0800752 avsync->last_pts = fpts;
753 if (time_diff(&now, &avsync->sync_lost_print_time) >=
754 SYNC_LOST_PRINT_THRESHOLD) {
Song Zhaof46932e2021-05-21 01:51:45 -0700755 log_warn("[%d]sync lost systime:%u fpts:%u lost:%u",
Song Zhaoea5a0412021-01-18 16:40:08 -0800756 avsync->session_id, systime, fpts, avsync->sync_lost_cnt);
Song Zhao5d2b4772021-01-18 16:40:08 -0800757 avsync->sync_lost_cnt = 0;
yongchun.li0ee6e372021-08-20 04:26:04 -0700758 clock_gettime(CLOCK_MONOTONIC_RAW, &avsync->sync_lost_print_time);
Song Zhao5d2b4772021-01-18 16:40:08 -0800759 } else
760 avsync->sync_lost_cnt++;
761 }
Song Zhaod62bb392021-04-23 12:25:49 -0700762
763 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP &&
764 LIVE_MODE(avsync->mode) &&
Song Zhaoa2985cb2021-06-24 12:01:47 -0700765 VALID_TS(avsync->last_pts) &&
Song Zhao065800e2021-05-26 15:56:06 -0700766 abs_diff(avsync->last_pts, fpts) > STREAM_DISC_THRES) {
Song Zhaod62bb392021-04-23 12:25:49 -0700767 /* outlier by stream error */
768 avsync->outlier_cnt++;
Song Zhao065800e2021-05-26 15:56:06 -0700769 frame->duration = -1;
Song Zhaod62bb392021-04-23 12:25:49 -0700770 if (avsync->outlier_cnt < OUTLIER_MAX_CNT) {
771 log_info("render outlier %u", fpts);
772 return true;
773 }
774 }
775
776 avsync->outlier_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800777 avsync->state = AV_SYNC_STAT_SYNC_LOST;
778 avsync->phase_set = false;
Song Zhaode5f73b2021-07-23 22:38:07 -0700779 avsync->phase = 0;
Song Zhaoa58c3e92021-03-09 18:52:55 -0800780 reset_pattern(avsync->pattern_detector);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700781
782 if (LIVE_MODE(avsync->mode) && avsync->last_disc_pts != fpts) {
Song Zhaod62bb392021-04-23 12:25:49 -0700783 log_info ("[%d]video disc %u --> %u",
Song Zhaoa2985cb2021-06-24 12:01:47 -0700784 avsync->session_id, systime, fpts);
Song Zhao409739b2021-05-12 22:21:40 -0700785 msync_session_set_video_dis(avsync->fd, fpts);
786 avsync->last_disc_pts = fpts;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700787 }
788
789 if ((int)(systime - fpts) > 0) {
790 if ((int)(systime - fpts) < avsync->disc_thres_max) {
791 /* catch up PCR */
Song Zhaof46932e2021-05-21 01:51:45 -0700792 return true;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700793 } else {
794 /* render according to FPS */
795 if (!VALID_TS(avsync->last_r_syst) ||
796 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
797 avsync->last_r_syst = systime;
798 return true;
799 }
800 return false;
801 }
802 } else if (LIVE_MODE(avsync->mode)) {
803 /* hold if the gap is small */
804 if ((int)(fpts - systime) < avsync->disc_thres_max) {
805 return false;
806 } else {
807 /* render according to FPS */
808 if (!VALID_TS(avsync->last_r_syst) ||
809 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
810 avsync->last_r_syst = systime;
811 return true;
812 }
813 return false;
814 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800815 }
816 }
817
Song Zhao52f55192021-05-06 10:52:21 -0700818 /* In some cases, keeping pattern will enlarge the gap */
819 if (abs_diff(systime, fpts) > AV_PATTERN_RESET_THRES &&
820 avsync->first_frame_toggled) {
821 reset_pattern(avsync->pattern_detector);
Song Zhaof46932e2021-05-21 01:51:45 -0700822 log_warn("sync pattern reset sys:%u fpts:%u",
Song Zhao52f55192021-05-06 10:52:21 -0700823 systime, fpts);
824 }
825
Song Zhaoc03ba122020-12-23 21:54:02 -0800826 expire = (int)(systime - fpts) >= 0;
827
828 /* scatter the frame in different vsync whenever possible */
829 if (expire && next_frame && next_frame->pts && toggle_cnt) {
830 /* multi frame expired in current vsync but no frame in next vsync */
Song Zhaoea5a0412021-01-18 16:40:08 -0800831 if (systime + interval < next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800832 expire = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800833 log_debug("[%d]unset expire systime:%d inter:%d next_pts:%d toggle_cnt:%d",
834 avsync->session_id, systime, interval, next_frame->pts, toggle_cnt);
Song Zhaoc03ba122020-12-23 21:54:02 -0800835 }
836 } else if (!expire && next_frame && next_frame->pts && !toggle_cnt
837 && avsync->first_frame_toggled) {
838 /* next vsync will have at least 2 frame expired */
Song Zhao35a82df2021-04-15 10:58:49 -0700839 if (systime + interval >= next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800840 expire = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800841 log_debug("[%d]set expire systime:%d inter:%d next_pts:%d",
842 avsync->session_id, systime, interval, next_frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800843 }
844 }
845
Song Zhaoa58c3e92021-03-09 18:52:55 -0800846 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP)
847 correct_pattern(avsync->pattern_detector, frame, next_frame,
848 (avsync->last_frame?avsync->last_frame->hold_period:0),
849 avsync->last_holding_peroid, systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800850 interval, &expire);
Song Zhaoc03ba122020-12-23 21:54:02 -0800851
852 if (expire) {
853 avsync->vpts = fpts;
854 /* phase adjustment */
855 if (!avsync->phase_set) {
yongchun.lia50b1e92021-08-07 01:11:54 +0000856 //always adjust to the half v-sync to give most pts tolerace and unify behavior
857 if ((int)(systime - fpts) >= 0 && (int)(fpts + interval - systime) > 0) {
858 avsync->phase = interval/2 + fpts - systime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800859 avsync->phase_set = true;
yongchun.lia50b1e92021-08-07 01:11:54 +0000860 log_info("[%d]adjust phase to %d", avsync->session_id, (int)avsync->phase);
Song Zhaoc03ba122020-12-23 21:54:02 -0800861 }
862 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800863 if (avsync->state != AV_SYNC_STAT_SYNC_SETUP)
Song Zhaoea5a0412021-01-18 16:40:08 -0800864 log_info("[%d]sync setup", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800865 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhao5d2b4772021-01-18 16:40:08 -0800866 avsync->sync_lost_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800867 }
868 return expire;
869}
870
Song Zhao35a82df2021-04-15 10:58:49 -0700871static bool pattern_detect(struct av_sync_session* avsync, int cur_period, int last_period)
Song Zhaoc03ba122020-12-23 21:54:02 -0800872{
Song Zhao35a82df2021-04-15 10:58:49 -0700873 bool ret = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800874 log_trace("[%d]cur_period: %d last_period: %d",
875 avsync->session_id, cur_period, last_period);
Song Zhao35a82df2021-04-15 10:58:49 -0700876 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P32, cur_period, last_period))
877 ret = true;
878 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P22, cur_period, last_period))
879 ret = true;
880 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P41, cur_period, last_period))
881 ret = true;
882 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P11, cur_period, last_period))
883 ret = true;
884
885 return ret;
Song Zhaoc03ba122020-12-23 21:54:02 -0800886}
887
888int av_sync_set_speed(void *sync, float speed)
889{
890 struct av_sync_session *avsync = (struct av_sync_session *)sync;
891
892 if (speed < 0.001f || speed > 100) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800893 log_error("[%d]wrong speed %f [0.0001, 100]", avsync->session_id, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -0800894 return -1;
895 }
896
Song Zhaoea5a0412021-01-18 16:40:08 -0800897 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER ||
898 avsync->mode == AV_SYNC_MODE_IPTV) {
899 log_info("[%d]ignore set speed in mode %d", avsync->session_id, avsync->mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800900 return 0;
Song Zhaoea5a0412021-01-18 16:40:08 -0800901 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800902
Song Zhaoea5a0412021-01-18 16:40:08 -0800903 avsync->speed = speed;
904
905 if (avsync->type == AV_SYNC_TYPE_AUDIO) {
906 if (speed == 1.0) {
907 avsync->mode = avsync->backup_mode;
908 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
909 } else {
910 avsync->backup_mode = avsync->mode;
911 avsync->mode = AV_SYNC_MODE_FREE_RUN;
912 log_info("[%d]audio to freerun mode", avsync->session_id);
913 }
914 }
915#if 0
Song Zhaoc03ba122020-12-23 21:54:02 -0800916 if (avsync->mode != AV_SYNC_MODE_VMASTER) {
917 log_info("ignore set speed in mode %d", avsync->mode);
918 return 0;
919 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800920#endif
Song Zhaoc03ba122020-12-23 21:54:02 -0800921
Song Zhaoea5a0412021-01-18 16:40:08 -0800922 log_info("session[%d] set rate to %f", avsync->session_id, speed);
923 return msync_session_set_rate(avsync->fd, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -0800924}
925
926int av_sync_change_mode(void *sync, enum sync_mode mode)
927{
928 struct av_sync_session *avsync = (struct av_sync_session *)sync;
929
930 if (!avsync)
931 return -1;
932
Song Zhaoea5a0412021-01-18 16:40:08 -0800933 if (msync_session_set_mode(avsync->fd, mode)) {
934 log_error("[%d]fail to set mode %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800935 return -1;
936 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800937 avsync->mode = mode;
Song Zhaoea5a0412021-01-18 16:40:08 -0800938 log_info("[%d]update sync mode to %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800939 return 0;
940}
941
Song Zhao01031bb2021-05-13 21:23:20 -0700942int av_sync_get_mode(void *sync, enum sync_mode *mode)
943{
944 struct av_sync_session *avsync = (struct av_sync_session *)sync;
945
946 if (!avsync || !mode)
947 return -1;
948
949 *mode = avsync->mode;
950 return 0;
951}
952
Song Zhaoc03ba122020-12-23 21:54:02 -0800953int av_sync_set_pause_pts(void *sync, pts90K pts)
954{
955 struct av_sync_session *avsync = (struct av_sync_session *)sync;
956
957 if (!avsync)
958 return -1;
959
960 avsync->pause_pts = pts;
Song Zhaoea5a0412021-01-18 16:40:08 -0800961 log_info("[%d]set pause pts: %u", avsync->session_id, pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800962 return 0;
963}
964
965int av_sync_set_pause_pts_cb(void *sync, pause_pts_done cb, void *priv)
966{
967 struct av_sync_session *avsync = (struct av_sync_session *)sync;
968
969 if (!avsync)
970 return -1;
971
972 avsync->pause_pts_cb = cb;
973 avsync->pause_cb_priv = priv;
974 return 0;
975}
Song Zhaoea5a0412021-01-18 16:40:08 -0800976
977static void trigger_audio_start_cb(struct av_sync_session *avsync,
978 avs_ascb_reason reason)
979{
980 if (avsync) {
981 pthread_mutex_lock(&avsync->lock);
982 if (avsync->audio_start) {
983 avsync->audio_start(avsync->audio_start_priv, reason);
984 avsync->session_started = true;
985 avsync->audio_start = NULL;
986 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
987 }
988 pthread_mutex_unlock(&avsync->lock);
989 }
990}
991
992avs_start_ret av_sync_audio_start(
993 void *sync,
994 pts90K pts,
995 pts90K delay,
996 audio_start_cb cb,
997 void *priv)
998{
999 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1000 uint32_t start_mode;
yongchun.li59e873d2021-07-07 11:42:38 -07001001 uint32_t systime;
Song Zhaoea5a0412021-01-18 16:40:08 -08001002 avs_start_ret ret = AV_SYNC_ASTART_ERR;
1003 bool create_poll_t = false;
1004
1005 if (!avsync)
1006 return ret;
1007
yongchun.li59e873d2021-07-07 11:42:38 -07001008 log_info("%d av_sync_audio_start pts(ms) %d delay %d ms",
1009 avsync->session_id, (int)pts/90, (int)delay/90);
Song Zhaoea5a0412021-01-18 16:40:08 -08001010
yongchun.li59e873d2021-07-07 11:42:38 -07001011 if (avsync->in_audio_switch &&
1012 avsync->audio_switch_state == AUDIO_SWITCH_STAT_AGAIN)
1013 {
1014 start_mode = AVS_START_SYNC;
1015 log_info("%d AUDIO_SWITCH_STAT_AGAIN", avsync->session_id);
1016 } else {
1017 if (msync_session_set_audio_start(avsync->fd, pts, delay, &start_mode))
1018 log_error("[%d]fail to set audio start", avsync->session_id);
1019 }
1020 if (avsync->in_audio_switch &&
1021 (avsync->audio_switch_state == AUDIO_SWITCH_STAT_RESET ||
1022 avsync->audio_switch_state == AUDIO_SWITCH_STAT_AGAIN)) {
1023 msync_session_get_wall(avsync->fd, &systime, NULL);
1024 if ((int)(systime - pts) > A_ADJ_THREDHOLD_LB &&
1025 start_mode == AVS_START_SYNC) {
1026 log_info("%d audio_switch audio need drop first.ahead %d ms",
1027 avsync->session_id, (int)(systime - pts)/90);
1028 ret = AV_SYNC_ASTART_AGAIN;
1029 avsync->audio_switch_state = AUDIO_SWITCH_STAT_AGAIN;
1030 goto exit;
1031 }
1032 else {
1033 int diff = (int)(pts - systime);
1034 log_info("%d audio_switch_state to start mode %d diff %d ms",
1035 avsync->session_id, start_mode, diff/90);
1036 avsync->audio_switch_state = AUDIO_SWITCH_STAT_START;
1037 if (diff < A_ADJ_THREDHOLD_LB) {
1038 log_info("%d orig mode %d already close enough direct start",
1039 avsync->session_id, start_mode);
1040 start_mode = AVS_START_SYNC;
1041 }
1042 }
yongchun.li107a6162021-05-05 02:38:57 -07001043 }
1044
Song Zhaoea5a0412021-01-18 16:40:08 -08001045 if (start_mode == AVS_START_SYNC) {
1046 ret = AV_SYNC_ASTART_SYNC;
1047 avsync->session_started = true;
Song Zhao065800e2021-05-26 15:56:06 -07001048 avsync->state = AV_SYNC_STAT_RUNNING;
Song Zhaod62bb392021-04-23 12:25:49 -07001049 } else if (start_mode == AVS_START_ASYNC) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001050 ret = AV_SYNC_ASTART_ASYNC;
Song Zhaod62bb392021-04-23 12:25:49 -07001051 avsync->state = AV_SYNC_STAT_RUNNING;
1052 } else if (start_mode == AVS_START_AGAIN) {
1053 ret = AV_SYNC_ASTART_AGAIN;
1054 }
1055
1056 if (ret == AV_SYNC_ASTART_AGAIN)
1057 goto exit;
Song Zhaoea5a0412021-01-18 16:40:08 -08001058
yongchun.li107a6162021-05-05 02:38:57 -07001059 if (avsync->mode == AV_SYNC_MODE_AMASTER || avsync->in_audio_switch) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001060 create_poll_t = true;
1061 if (start_mode == AVS_START_ASYNC) {
1062 if (!cb) {
1063 log_error("[%d]invalid cb", avsync->session_id);
1064 return AV_SYNC_ASTART_ERR;
1065 }
1066 avsync->audio_start = cb;
1067 avsync->audio_start_priv = priv;
1068 }
Song Zhaod62bb392021-04-23 12:25:49 -07001069 } else if (LIVE_MODE(avsync->mode))
Song Zhaoea5a0412021-01-18 16:40:08 -08001070 create_poll_t = true;
1071
Song Zhaod62bb392021-04-23 12:25:49 -07001072 if (create_poll_t && !avsync->poll_thread) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001073 int ret;
1074
1075 log_info("[%d]start poll thread", avsync->session_id);
1076 avsync->quit_poll = false;
1077 ret = pthread_create(&avsync->poll_thread, NULL, poll_thread, avsync);
1078 if (ret) {
1079 log_error("[%d]create poll thread errno %d", avsync->session_id, errno);
1080 return AV_SYNC_ASTART_ERR;
1081 }
1082 }
Song Zhaod62bb392021-04-23 12:25:49 -07001083 if (LIVE_MODE(avsync->mode)) {
Song Zhaod62bb392021-04-23 12:25:49 -07001084 msync_session_get_wall(avsync->fd, &systime, NULL);
1085 log_info("[%d]return %u w %u pts %u d %u",
1086 avsync->session_id, ret, systime, pts, delay);
1087 }
1088exit:
Song Zhaoea5a0412021-01-18 16:40:08 -08001089 log_info("[%d]return %u", avsync->session_id, ret);
1090 return ret;
1091}
1092
1093int av_sync_audio_render(
1094 void *sync,
1095 pts90K pts,
1096 struct audio_policy *policy)
1097{
1098 int ret = 0;
Song Zhao065800e2021-05-26 15:56:06 -07001099 bool out_lier = false;
Song Zhaoea5a0412021-01-18 16:40:08 -08001100 uint32_t systime;
1101 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1102 avs_audio_action action = AA_SYNC_AA_MAX;
1103
1104 if (!avsync || !policy)
1105 return -1;
1106
yongchun.li107a6162021-05-05 02:38:57 -07001107 msync_session_get_wall(avsync->fd, &systime, NULL);
1108
1109 log_trace("audio render pts %u, systime %u, mode %u diff ms %d",
1110 pts, systime, avsync->mode, (int)(pts-systime)/90);
1111
1112 if (avsync->in_audio_switch
1113 && avsync->audio_switch_state == AUDIO_SWITCH_STAT_START) {
1114 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_HB) {
1115 log_info("Audio pts in system range sys %u pts %u\n", systime, pts);
1116 avsync->audio_switch_state = AUDIO_SWITCH_STAT_FINISH;
1117 action = AV_SYNC_AA_RENDER;
1118 } else if ((int)(systime - pts) > 0) {
1119 log_info("[%d] audio change drop %d ms sys %u pts %u", avsync->session_id,
1120 (int)(systime - pts)/90, systime, pts);
1121 action = AV_SYNC_AA_DROP;
1122 } else {
1123 action = AV_SYNC_AA_INSERT;
1124 log_info("[%d] audio change insert %d ms sys %u pts %u", avsync->session_id,
1125 (int)(pts - systime)/90, systime, pts);
1126 }
1127 goto done;
1128 }
1129
Song Zhaoea5a0412021-01-18 16:40:08 -08001130 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
1131 avsync->mode == AV_SYNC_MODE_AMASTER) {
1132 action = AV_SYNC_AA_RENDER;
1133 goto done;
1134 }
1135
Song Zhaod62bb392021-04-23 12:25:49 -07001136 /* stopping procedure, unblock audio rendering */
1137 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER &&
1138 avsync->active_mode == AV_SYNC_MODE_FREE_RUN) {
1139 action = AV_SYNC_AA_DROP;
1140 goto done;
1141 }
1142
Song Zhao7daf3a12021-05-10 22:22:25 -07001143 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
1144 avsync->mode == AV_SYNC_MODE_AMASTER) {
1145 action = AV_SYNC_AA_RENDER;
1146 goto done;
1147 }
1148
Song Zhaod62bb392021-04-23 12:25:49 -07001149 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP &&
1150 LIVE_MODE(avsync->mode) &&
1151 abs_diff(systime, pts) > STREAM_DISC_THRES) {
1152 /* outlier by stream error */
1153 avsync->outlier_cnt++;
1154 if (avsync->outlier_cnt > OUTLIER_MAX_CNT) {
1155 /* treat as disc, just drop current frame */
1156 avsync->state = AV_SYNC_STAT_SYNC_LOST;
1157 avsync->outlier_cnt = 0;
1158 action = AV_SYNC_AA_DROP;
1159 systime = pts;
Song Zhaod62bb392021-04-23 12:25:49 -07001160 goto done;
1161 }
1162 log_info("[%d]ignore outlier %u", avsync->session_id, pts);
1163 pts = systime;
1164 action = AV_SYNC_AA_RENDER;
Song Zhao065800e2021-05-26 15:56:06 -07001165 out_lier = true;
Song Zhaod62bb392021-04-23 12:25:49 -07001166 goto done;
1167 }
1168
1169 avsync->outlier_cnt = 0;
1170 /* low bound from sync_lost to sync_setup */
1171 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_LB) {
1172 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
1173 action = AV_SYNC_AA_RENDER;
1174 goto done;
1175 }
1176
1177 /* high bound of sync_setup */
1178 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_HB &&
1179 avsync->state != AV_SYNC_STAT_SYNC_LOST) {
1180 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhaoea5a0412021-01-18 16:40:08 -08001181 action = AV_SYNC_AA_RENDER;
1182 goto done;
1183 }
1184
1185 if ((int)(systime - pts) > 0) {
Song Zhaod62bb392021-04-23 12:25:49 -07001186 avsync->state = AV_SYNC_STAT_SYNC_LOST;
Song Zhaoea5a0412021-01-18 16:40:08 -08001187 action = AV_SYNC_AA_DROP;
1188 goto done;
1189 }
1190
1191 if ((int)(systime - pts) < 0) {
Song Zhaod62bb392021-04-23 12:25:49 -07001192 avsync->state = AV_SYNC_STAT_SYNC_LOST;
Song Zhaoea5a0412021-01-18 16:40:08 -08001193 action = AV_SYNC_AA_INSERT;
1194 goto done;
1195 }
1196
1197done:
1198 policy->action = action;
1199 policy->delta = (int)(systime - pts);
1200 if (action == AV_SYNC_AA_RENDER) {
1201 avsync->apts = pts;
yongchun.li107a6162021-05-05 02:38:57 -07001202 if (!avsync->in_audio_switch) {
Song Zhao065800e2021-05-26 15:56:06 -07001203 if (!out_lier)
1204 msync_session_update_apts(avsync->fd, systime, pts, 0);
Song Zhaof46932e2021-05-21 01:51:45 -07001205 log_debug("[%d]return %d sys %u - pts %u = %d",
Song Zhao409739b2021-05-12 22:21:40 -07001206 avsync->session_id, action, systime, pts, systime - pts);
yongchun.li107a6162021-05-05 02:38:57 -07001207 } else if(avsync->audio_switch_state == AUDIO_SWITCH_STAT_FINISH) {
1208 msync_session_update_apts(avsync->fd, systime, pts, 0);
1209 log_info("[%d] audio switch done sys %u pts %u",
1210 avsync->session_id, systime, pts);
1211 msync_session_set_audio_switch(avsync->fd, false);
1212 avsync->in_audio_switch = false;
1213 avsync->audio_switch_state = AUDIO_SWITCH_STAT_INIT;
1214 } else {
1215 log_trace("[%d] in audio switch ret %d sys %u - pts %u = %d",
1216 avsync->session_id, action, systime, pts, systime - pts);
1217 }
Song Zhaoa2985cb2021-06-24 12:01:47 -07001218 avsync->audio_drop_cnt = 0;
Song Zhaoea5a0412021-01-18 16:40:08 -08001219 } else {
Song Zhaoa2985cb2021-06-24 12:01:47 -07001220 if (abs_diff(systime, pts) > avsync->disc_thres_min &&
yongchun.li085b5a42021-05-24 04:22:53 -07001221 avsync->last_disc_pts != pts &&
1222 !avsync->in_audio_switch) {
Song Zhao409739b2021-05-12 22:21:40 -07001223 log_info ("[%d]audio disc %u --> %u",
1224 avsync->session_id, systime, pts);
1225 msync_session_set_audio_dis(avsync->fd, pts);
1226 avsync->last_disc_pts = pts;
Song Zhaoa2985cb2021-06-24 12:01:47 -07001227 } else if (action == AV_SYNC_AA_DROP) {
yongchun.li0ee6e372021-08-20 04:26:04 -07001228 struct timespec now;
Song Zhaoa2985cb2021-06-24 12:01:47 -07001229
1230 /* dropping recovery */
yongchun.li0ee6e372021-08-20 04:26:04 -07001231 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
Song Zhaoa2985cb2021-06-24 12:01:47 -07001232 if (!avsync->audio_drop_cnt)
1233 avsync->audio_drop_start = now;
1234 avsync->audio_drop_cnt++;
1235 if (time_diff(&now, &avsync->audio_drop_start) > 500000) {
1236 log_info ("[%d]audio keep dropping sys %u vs a %u",
1237 avsync->session_id, systime, pts);
1238 msync_session_set_audio_dis(avsync->fd, pts);
1239 }
Song Zhao409739b2021-05-12 22:21:40 -07001240 }
Song Zhaoa2985cb2021-06-24 12:01:47 -07001241 if (action != AV_SYNC_AA_DROP)
1242 avsync->audio_drop_cnt = 0;
Song Zhaof46932e2021-05-21 01:51:45 -07001243 log_debug("[%d]return %d sys %u - pts %u = %d",
Song Zhaod62bb392021-04-23 12:25:49 -07001244 avsync->session_id, action, systime, pts, systime - pts);
Song Zhaoea5a0412021-01-18 16:40:08 -08001245 }
1246
1247 return ret;
1248}
1249
1250int av_sync_get_clock(void *sync, pts90K *pts)
1251{
1252 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1253
1254 if (!avsync || !pts)
1255 return -1;
1256 return msync_session_get_wall(avsync->fd, pts, NULL);
1257}
1258
1259static void handle_mode_change_a(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -07001260 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -08001261{
Song Zhaoe208d692021-04-19 15:38:52 -07001262 log_info("[%d]amode %d mode %d v/a/vt %d/%d/%d", avsync->session_id,
1263 avsync->active_mode, avsync->mode, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -08001264 if (avsync->active_mode == AV_SYNC_MODE_AMASTER) {
1265 float speed;
1266 if (avsync->start_policy == AV_SYNC_START_ALIGN &&
Song Zhaoe208d692021-04-19 15:38:52 -07001267 a_active && avsync->audio_start) {
yongchun.li107a6162021-05-05 02:38:57 -07001268 if (v_active || v_timeout || avsync->in_audio_switch) {
Song Zhaoe208d692021-04-19 15:38:52 -07001269 log_info("audio start cb");
1270 trigger_audio_start_cb(avsync, AV_SYNC_ASCB_OK);
yongchun.li107a6162021-05-05 02:38:57 -07001271 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001272 }
1273
1274 if (!msync_session_get_rate(avsync->fd, &speed)) {
1275 /* speed change is triggered by asink,
1276 * attached audio HAL will handle it
1277 */
1278 if (speed != avsync->speed)
1279 log_info("[%d]new rate %f", avsync->session_id, speed);
1280 if (speed == 1.0) {
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001281 if (avsync->mode != avsync->backup_mode) {
1282 avsync->mode = avsync->backup_mode;
1283 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
1284 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001285 } else {
1286 avsync->backup_mode = avsync->mode;
1287 avsync->mode = AV_SYNC_MODE_FREE_RUN;
1288 log_info("[%d]audio to freerun mode", avsync->session_id);
1289 }
1290 avsync->speed = speed;
1291 }
Song Zhaod62bb392021-04-23 12:25:49 -07001292 } else if (avsync->active_mode == AV_SYNC_MODE_PCR_MASTER) {
1293 struct session_debug debug;
1294 if (!msync_session_get_debug_mode(avsync->fd, &debug)) {
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001295 if (debug.debug_freerun && !avsync->debug_freerun) {
Song Zhaod62bb392021-04-23 12:25:49 -07001296 avsync->backup_mode = avsync->mode;
1297 avsync->mode = AV_SYNC_MODE_FREE_RUN;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001298 avsync->debug_freerun = true;
Song Zhaod62bb392021-04-23 12:25:49 -07001299 log_warn("[%d]audio to freerun mode", avsync->session_id);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001300 } else if (!debug.debug_freerun && avsync->debug_freerun) {
Song Zhaod62bb392021-04-23 12:25:49 -07001301 avsync->mode = avsync->backup_mode;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001302 avsync->debug_freerun = false;
Song Zhaod62bb392021-04-23 12:25:49 -07001303 log_warn("[%d]audio back to mode %d",
1304 avsync->session_id, avsync->mode);
1305 }
1306 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001307 }
1308}
1309
1310static void handle_mode_change_v(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -07001311 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -08001312{
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001313 struct session_debug debug;
1314
Song Zhaoea5a0412021-01-18 16:40:08 -08001315 log_info("[%d]amode mode %d %d v/a %d/%d", avsync->session_id,
1316 avsync->active_mode, avsync->mode, v_active, a_active);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001317 if (!msync_session_get_debug_mode(avsync->fd, &debug)) {
1318 if (debug.debug_freerun && !avsync->debug_freerun) {
1319 avsync->backup_mode = avsync->mode;
1320 avsync->mode = AV_SYNC_MODE_FREE_RUN;
1321 avsync->debug_freerun = true;
1322 log_warn("[%d]video to freerun mode", avsync->session_id);
1323 } else if (!debug.debug_freerun && avsync->debug_freerun) {
1324 avsync->mode = avsync->backup_mode;
1325 avsync->debug_freerun = false;
1326 log_warn("[%d]video back to mode %d",
1327 avsync->session_id, avsync->mode);
Song Zhaod62bb392021-04-23 12:25:49 -07001328 }
1329 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001330}
1331
1332static void * poll_thread(void * arg)
1333{
1334 int ret = 0;
1335 struct av_sync_session *avsync = (struct av_sync_session *)arg;
1336 const int fd = avsync->fd;
1337 struct pollfd pfd = {
1338 /* default blocking capture */
1339 .events = POLLIN | POLLRDNORM | POLLPRI | POLLOUT | POLLWRNORM,
1340 .fd = avsync->fd,
1341 };
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001342 enum src_flag sflag = SRC_A;
Song Zhaoea5a0412021-01-18 16:40:08 -08001343
1344 prctl (PR_SET_NAME, "avs_poll");
1345 log_info("[%d]enter", avsync->session_id);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001346
1347 if (avsync->type == AV_SYNC_TYPE_AUDIO)
1348 sflag = SRC_A;
1349 else if (avsync->type == AV_SYNC_TYPE_VIDEO)
1350 sflag = SRC_V;
1351
Song Zhaoea5a0412021-01-18 16:40:08 -08001352 while (!avsync->quit_poll) {
1353 for (;;) {
1354 ret = poll(&pfd, 1, 10);
1355 if (ret > 0)
1356 break;
1357 if (avsync->quit_poll)
1358 goto exit;
1359 if (errno == EINTR)
1360 continue;
1361 }
1362
1363 /* error handling */
1364 if (pfd.revents & POLLERR)
1365 log_error("[%d]POLLERR received", avsync->session_id);
1366
Song Zhaod62bb392021-04-23 12:25:49 -07001367 /* mode change. Non-exclusive wait so all the processes
1368 * shall be woken up
1369 */
Song Zhaoea5a0412021-01-18 16:40:08 -08001370 if (pfd.revents & POLLPRI) {
Song Zhaoe208d692021-04-19 15:38:52 -07001371 bool v_active, a_active, v_timeout;
Song Zhaoea5a0412021-01-18 16:40:08 -08001372
1373 msync_session_get_stat(fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001374 &v_active, &a_active, &v_timeout, &avsync->in_audio_switch, sflag);
Song Zhaoea5a0412021-01-18 16:40:08 -08001375
1376 if (avsync->type == AV_SYNC_TYPE_AUDIO)
Song Zhaoe208d692021-04-19 15:38:52 -07001377 handle_mode_change_a(avsync, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -08001378 else if (avsync->type == AV_SYNC_TYPE_VIDEO)
Song Zhaoe208d692021-04-19 15:38:52 -07001379 handle_mode_change_v(avsync, v_active, a_active, v_timeout);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001380 usleep(10000);
Song Zhaoea5a0412021-01-18 16:40:08 -08001381 }
1382 }
1383exit:
1384 log_info("[%d]quit", avsync->session_id);
1385 return NULL;
1386}
1387
Song Zhaod62bb392021-04-23 12:25:49 -07001388int av_sync_set_pcr_clock(void *sync, pts90K pts, uint64_t mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -08001389{
1390 struct av_sync_session *avsync = (struct av_sync_session *)sync;
wei.dubcc2ed22021-05-19 07:16:10 -04001391 struct pcr_info pcr;
1392 enum pcr_monitor_status status;
1393 int ppm;
Song Zhaoea5a0412021-01-18 16:40:08 -08001394 if (!avsync)
1395 return -1;
1396
1397 if (avsync->type != AV_SYNC_TYPE_PCR)
1398 return -2;
1399
wei.dubcc2ed22021-05-19 07:16:10 -04001400 pcr.monoclk = mono_clock / 1000;
1401 pcr.pts = (long long) pts * 1000 / 90;
1402 pcr_monitor_process(avsync->pcr_monitor, &pcr);
1403
1404 status = pcr_monitor_get_status(avsync->pcr_monitor);
1405
1406 if (status >= DEVIATION_READY) {
1407 pcr_monitor_get_deviation(avsync->pcr_monitor, &ppm);
1408 if (avsync->ppm != ppm) {
1409 avsync->ppm = ppm;
1410 log_info("[%d]ppm:%d", avsync->session_id, ppm);
1411 if (msync_session_set_clock_dev(avsync->fd, ppm))
1412 log_error("set clock dev fail");
1413 }
1414 }
1415
Song Zhaod62bb392021-04-23 12:25:49 -07001416 return msync_session_set_pcr(avsync->fd, pts, mono_clock);
Song Zhaoea5a0412021-01-18 16:40:08 -08001417}
1418
Song Zhaod62bb392021-04-23 12:25:49 -07001419int av_sync_get_pcr_clock(void *sync, pts90K *pts, uint64_t * mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -08001420{
1421 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1422
1423 if (!avsync)
1424 return -1;
1425
Song Zhaod62bb392021-04-23 12:25:49 -07001426 return msync_session_get_pcr(avsync->fd, pts, mono_clock);
Song Zhaoea5a0412021-01-18 16:40:08 -08001427}
1428
1429int av_sync_set_session_name(void *sync, const char *name)
1430{
1431 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1432
1433 if (!avsync)
1434 return -1;
1435
1436 return msync_session_set_name(avsync->fd, name);
1437}
yongchun.li107a6162021-05-05 02:38:57 -07001438
1439int av_sync_set_audio_switch(void *sync, bool start)
1440{
1441 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1442 bool v_active, a_active, v_timeout;
1443
1444 if (!avsync)
1445 return -1;
1446 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
1447 &v_active, &a_active,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001448 &v_timeout, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -07001449 log_error("[%d] can not get session state",
1450 avsync->session_id);
1451 return -1;
1452 }
1453 if (!v_active || !a_active) {
1454 log_error("[%d] no apply if not AV both active v %d a %d",
1455 avsync->session_id, v_active, a_active);
1456 return -1;
1457 }
1458 if (msync_session_set_audio_switch(avsync->fd, start)) {
1459 log_error("[%d]fail to set audio switch %d", avsync->session_id, start);
1460 return -1;
1461 }
1462 avsync->in_audio_switch = start;
1463 avsync->audio_switch_state = AUDIO_SWITCH_STAT_INIT;
1464 log_info("[%d]update audio switch to %d", avsync->session_id, start);
1465 return 0;
1466}
1467
1468int av_sync_get_audio_switch(void *sync, bool *start)
1469{
1470 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1471
1472 if (!avsync)
1473 return -1;
1474 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001475 NULL, NULL, NULL, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -07001476 log_error("[%d] can not audio seamless switch state",
1477 avsync->session_id);
1478 return -1;
1479 }
1480 if (start) *start = avsync->in_audio_switch;
1481 return 0;
Song Zhao7daf3a12021-05-10 22:22:25 -07001482}
Song Zhao8039f562021-05-18 18:11:25 -07001483
1484enum clock_recovery_stat av_sync_get_clock_devication(void *sync, int32_t *ppm)
1485{
1486 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1487
wei.dubcc2ed22021-05-19 07:16:10 -04001488 if (!avsync || !ppm)
1489 return CLK_RECOVERY_ERR;
1490 if (avsync->mode != AV_SYNC_MODE_PCR_MASTER)
Song Zhao8039f562021-05-18 18:11:25 -07001491 return CLK_RECOVERY_NOT_RUNNING;
1492
wei.dubcc2ed22021-05-19 07:16:10 -04001493 if (msync_session_get_clock_dev(avsync->fd, ppm))
1494 return CLK_RECOVERY_ERR;
1495
1496 if (*ppm == 0)
1497 return CLK_RECOVERY_ONGOING;
1498 else
1499 return CLK_RECOVERY_READY;
Song Zhao8039f562021-05-18 18:11:25 -07001500}