blob: e6a5cc551720ba6d882175049e0f02dbcf1b3c9c [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;
Song Zhaoc03ba122020-12-23 21:54:02 -080059
Song Zhaoea5a0412021-01-18 16:40:08 -080060 /* playback time, will stop increasing during pause */
61 pts90K vpts;
62 pts90K apts;
63
64 /* phase adjustment of stream time for rate control (Video ONLY) */
Song Zhaoc03ba122020-12-23 21:54:02 -080065 pts90K phase;
66 bool phase_set;
67
68 /* pts of last rendered frame */
Song Zhaoea5a0412021-01-18 16:40:08 -080069 pts90K last_wall;
Song Zhaoc03ba122020-12-23 21:54:02 -080070 pts90K last_pts;
71 struct vframe *last_frame;
72
Song Zhaoe0bf6ad2021-07-09 11:28:42 -070073 /* pts of last pushed frame */
74 pts90K last_q_pts;
75
Song Zhaoc03ba122020-12-23 21:54:02 -080076 bool first_frame_toggled;
Song Zhaoc03ba122020-12-23 21:54:02 -080077 bool paused;
Song Zhaoea5a0412021-01-18 16:40:08 -080078 enum sync_state state;
Song Zhaoc03ba122020-12-23 21:54:02 -080079 void *pattern_detector;
80 void *frame_q;
Song Zhaoc03ba122020-12-23 21:54:02 -080081
Song Zhaoea5a0412021-01-18 16:40:08 -080082 /* start control */
83 int start_thres;
84 audio_start_cb audio_start;
85 void *audio_start_priv;
86
87 /* render property */
Song Zhaoc03ba122020-12-23 21:54:02 -080088 int delay;
89 pts90K vsync_interval;
90
91 /* state lock */
92 pthread_mutex_t lock;
93 /* pattern */
94 int last_holding_peroid;
Song Zhaoea5a0412021-01-18 16:40:08 -080095 bool session_started;
Song Zhaoc03ba122020-12-23 21:54:02 -080096
97 float speed;
98
Song Zhaoc03ba122020-12-23 21:54:02 -080099 /* pause pts */
100 pts90K pause_pts;
101 pause_pts_done pause_pts_cb;
102 void *pause_cb_priv;
Song Zhao5d2b4772021-01-18 16:40:08 -0800103
104 /* log control */
Song Zhaoa2985cb2021-06-24 12:01:47 -0700105 uint32_t last_log_syst;
Song Zhao5d2b4772021-01-18 16:40:08 -0800106 uint32_t sync_lost_cnt;
107 struct timeval sync_lost_print_time;
Song Zhaoea5a0412021-01-18 16:40:08 -0800108
109 pthread_t poll_thread;
110 /* pcr master, IPTV only */
111 bool quit_poll;
112 enum sync_mode active_mode;
Song Zhaof46932e2021-05-21 01:51:45 -0700113 uint32_t disc_thres_min;
114 uint32_t disc_thres_max;
Song Zhao35a82df2021-04-15 10:58:49 -0700115
116 /* error detection */
117 uint32_t last_poptime;
Song Zhaod62bb392021-04-23 12:25:49 -0700118 uint32_t outlier_cnt;
Song Zhao409739b2021-05-12 22:21:40 -0700119 pts90K last_disc_pts;
120
yongchun.li107a6162021-05-05 02:38:57 -0700121 // indicate set audio switch
122 bool in_audio_switch;
123 enum audio_switch_state_ audio_switch_state;
wei.dubcc2ed22021-05-19 07:16:10 -0400124
125 //pcr monitor handle
126 void *pcr_monitor;
127 int ppm;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700128
129 //video FPS detection
130 pts90K last_fpts;
131 int fps_interval;
132 int fps_interval_acc;
133 int fps_cnt;
134
135 //video freerun with rate control
136 uint32_t last_r_syst;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700137 bool debug_freerun;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700138
139 //Audio dropping detection
140 uint32_t audio_drop_cnt;
141 struct timeval audio_drop_start;
Song Zhaoc03ba122020-12-23 21:54:02 -0800142};
143
144#define MAX_FRAME_NUM 32
145#define DEFAULT_START_THRESHOLD 2
146#define TIME_UNIT90K (90000)
Song Zhaof46932e2021-05-21 01:51:45 -0700147#define AV_DISC_THRES_MIN (TIME_UNIT90K / 3)
148#define AV_DISC_THRES_MAX (TIME_UNIT90K * 10)
Song Zhao7daf3a12021-05-10 22:22:25 -0700149#define A_ADJ_THREDHOLD_HB (900 * 6) //60ms
150#define A_ADJ_THREDHOLD_LB (900 * 2) //20ms
Song Zhao52f55192021-05-06 10:52:21 -0700151#define AV_PATTERN_RESET_THRES (TIME_UNIT90K / 10)
Song Zhao5d2b4772021-01-18 16:40:08 -0800152#define SYNC_LOST_PRINT_THRESHOLD 10000000 //10 seconds In micro seconds
Song Zhaod62bb392021-04-23 12:25:49 -0700153#define LIVE_MODE(mode) ((mode) == AV_SYNC_MODE_PCR_MASTER || (mode) == AV_SYNC_MODE_IPTV)
154
Song Zhao065800e2021-05-26 15:56:06 -0700155#define STREAM_DISC_THRES (TIME_UNIT90K / 10)
Song Zhaod62bb392021-04-23 12:25:49 -0700156#define OUTLIER_MAX_CNT 8
Song Zhaoa2985cb2021-06-24 12:01:47 -0700157#define VALID_TS(x) ((x) != -1)
Song Zhaoc03ba122020-12-23 21:54:02 -0800158
159static uint64_t time_diff (struct timeval *b, struct timeval *a);
160static bool frame_expire(struct av_sync_session* avsync,
161 uint32_t systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800162 uint32_t interval,
Song Zhaoc03ba122020-12-23 21:54:02 -0800163 struct vframe * frame,
164 struct vframe * next_frame,
165 int toggle_cnt);
Song Zhao35a82df2021-04-15 10:58:49 -0700166static bool pattern_detect(struct av_sync_session* avsync,
Song Zhaoc03ba122020-12-23 21:54:02 -0800167 int cur_period,
168 int last_period);
Song Zhaoea5a0412021-01-18 16:40:08 -0800169static void * poll_thread(void * arg);
170static void trigger_audio_start_cb(struct av_sync_session *avsync,
171 avs_ascb_reason reason);
Song Zhaoc03ba122020-12-23 21:54:02 -0800172
Song Zhaoea5a0412021-01-18 16:40:08 -0800173int av_sync_open_session(int *session_id)
174{
175 int fd = msync_create_session();
176 int id, rc;
177
178 if (fd < 0) {
179 log_error("fail");
180 return -1;
181 }
182 rc = ioctl(fd, AMSYNC_IOC_ALLOC_SESSION, &id);
183 if (rc) {
184 log_error("new session errno:%d", errno);
185 return rc;
186 }
187 *session_id = id;
188 return fd;
189}
190
191void av_sync_close_session(int session)
192{
193 msync_destory_session(session);
194}
195
196static void* create_internal(int session_id,
Song Zhaoc03ba122020-12-23 21:54:02 -0800197 enum sync_mode mode,
Song Zhaoea5a0412021-01-18 16:40:08 -0800198 enum sync_type type,
Song Zhaoc03ba122020-12-23 21:54:02 -0800199 int start_thres,
Song Zhaoea5a0412021-01-18 16:40:08 -0800200 bool attach)
Song Zhaoc03ba122020-12-23 21:54:02 -0800201{
202 struct av_sync_session *avsync = NULL;
Song Zhaoea5a0412021-01-18 16:40:08 -0800203 char dev_name[20];
Song Zhaoc03ba122020-12-23 21:54:02 -0800204
205 avsync = (struct av_sync_session *)calloc(1, sizeof(*avsync));
206 if (!avsync) {
207 log_error("OOM");
208 return NULL;
209 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800210
211 if (type == AV_SYNC_TYPE_VIDEO) {
212 avsync->pattern_detector = create_pattern_detector();
213 if (!avsync->pattern_detector) {
214 log_error("pd create fail");
215 goto err;
216 }
217
218 if (!start_thres)
219 avsync->start_thres = DEFAULT_START_THRESHOLD;
220 else {
221 if (start_thres > 5) {
222 log_error("start_thres too big: %d", start_thres);
223 goto err2;
224 }
225 avsync->start_thres = start_thres;
226 }
227 avsync->phase_set = false;
228 avsync->first_frame_toggled = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800229 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800230
231 avsync->type = type;
Song Zhaoc03ba122020-12-23 21:54:02 -0800232 avsync->state = AV_SYNC_STAT_INIT;
Song Zhaoc03ba122020-12-23 21:54:02 -0800233 avsync->paused = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800234 avsync->session_id = session_id;
Song Zhaoea5a0412021-01-18 16:40:08 -0800235 avsync->backup_mode = mode;
Song Zhaoc03ba122020-12-23 21:54:02 -0800236 avsync->last_frame = NULL;
Song Zhaoea5a0412021-01-18 16:40:08 -0800237 avsync->session_started = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800238 avsync->speed = 1.0f;
239 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
Song Zhao409739b2021-05-12 22:21:40 -0700240 avsync->vsync_interval = -1;
241 avsync->last_disc_pts = -1;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700242 avsync->last_log_syst = -1;
243 avsync->last_pts = -1;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700244 avsync->last_q_pts = -1;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700245 avsync->last_wall = -1;
246 avsync->fps_interval = -1;
247 avsync->last_r_syst = -1;
Song Zhaof46932e2021-05-21 01:51:45 -0700248 if (msync_session_get_disc_thres(session_id,
249 &avsync->disc_thres_min, &avsync->disc_thres_max)) {
250 log_error("fail to get disc thres", dev_name, errno);
251 avsync->disc_thres_min = AV_DISC_THRES_MIN;
252 avsync->disc_thres_max = AV_DISC_THRES_MAX;
253 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800254
255 pthread_mutex_init(&avsync->lock, NULL);
Song Zhaof46932e2021-05-21 01:51:45 -0700256 log_info("[%d] mode %d type %d start_thres %d disc_thres %u/%u",
257 session_id, mode, type, start_thres,
258 avsync->disc_thres_min, avsync->disc_thres_max);
Song Zhaoea5a0412021-01-18 16:40:08 -0800259
260 snprintf(dev_name, sizeof(dev_name), "/dev/%s%d", SESSION_DEV, session_id);
261 avsync->fd = open(dev_name, O_RDONLY | O_CLOEXEC);
262 if (avsync->fd < 0) {
263 log_error("open %s errno %d", dev_name, errno);
264 goto err2;
265 }
266
wei.dubcc2ed22021-05-19 07:16:10 -0400267 if (avsync->type == AV_SYNC_TYPE_PCR) {
268 if (pcr_monitor_init(&avsync->pcr_monitor)) {
269 log_error("pcr monitor init");
270 goto err2;
271 }
272 }
273
Song Zhaoea5a0412021-01-18 16:40:08 -0800274 if (!attach) {
275 msync_session_set_mode(avsync->fd, mode);
276 avsync->mode = mode;
277 } else {
278 avsync->attached = true;
279 if (msync_session_get_mode(avsync->fd, &avsync->mode)) {
280 log_error("get mode");
wei.dubcc2ed22021-05-19 07:16:10 -0400281 goto err3;
Song Zhaoea5a0412021-01-18 16:40:08 -0800282 }
283 avsync->backup_mode = avsync->mode;
284 if (msync_session_get_start_policy(avsync->fd, &avsync->start_policy)) {
285 log_error("get policy");
wei.dubcc2ed22021-05-19 07:16:10 -0400286 goto err3;
Song Zhaoea5a0412021-01-18 16:40:08 -0800287 }
yongchun.li107a6162021-05-05 02:38:57 -0700288 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700289 NULL, NULL, NULL, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -0700290 log_error("get state");
wei.dubcc2ed22021-05-19 07:16:10 -0400291 goto err3;
yongchun.li107a6162021-05-05 02:38:57 -0700292 }
293 if (avsync->in_audio_switch) {
294 log_info("audio_switch_state reseted the audio");
295 avsync->audio_switch_state = AUDIO_SWITCH_STAT_RESET;
296 }
297
Song Zhaoea5a0412021-01-18 16:40:08 -0800298 log_info("[%d]retrieve sync mode %d policy %d",
299 session_id, avsync->mode, avsync->start_policy);
300 }
301
Song Zhaoc03ba122020-12-23 21:54:02 -0800302 return avsync;
wei.dubcc2ed22021-05-19 07:16:10 -0400303err3:
304 if (avsync->pcr_monitor)
305 pcr_monitor_destroy(avsync->pcr_monitor);
Song Zhaoea5a0412021-01-18 16:40:08 -0800306err2:
307 destroy_pattern_detector(avsync->pattern_detector);
308err:
309 free(avsync);
310 return NULL;
311}
312
313void* av_sync_create(int session_id,
314 enum sync_mode mode,
315 enum sync_type type,
316 int start_thres)
317{
318 return create_internal(session_id, mode,
319 type, start_thres, false);
320}
321
322void* av_sync_attach(int session_id, enum sync_type type)
323{
324 return create_internal(session_id, AV_SYNC_MODE_MAX,
325 type, 0, true);
326}
327
328int av_sync_video_config(void *sync, struct video_config* config)
329{
330 struct av_sync_session *avsync = (struct av_sync_session *)sync;
331
332 if (!avsync || !config)
333 return -1;
334
335 if (config->delay != 1 && config->delay != 2) {
336 log_error("invalid delay: %d\n", config->delay);
337 return -1;
338 }
339
340 avsync->delay = config->delay;
341
342 log_info("[%d] delay: %d",
343 avsync->session_id, config->delay);
344 return 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800345}
346
347static int internal_stop(struct av_sync_session *avsync)
348{
349 int ret = 0;
350 struct vframe *frame;
351
352 pthread_mutex_lock(&avsync->lock);
Song Zhaoc03ba122020-12-23 21:54:02 -0800353 while (!dqueue_item(avsync->frame_q, (void **)&frame)) {
354 frame->free(frame);
355 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800356 avsync->state = AV_SYNC_STAT_INIT;
Song Zhaoc03ba122020-12-23 21:54:02 -0800357 pthread_mutex_unlock(&avsync->lock);
358 return ret;
359}
360
361/* destroy and detach from kernel session */
362void av_sync_destroy(void *sync)
363{
364 struct av_sync_session *avsync = (struct av_sync_session *)sync;
365
366 if (!avsync)
367 return;
368
Song Zhaoea5a0412021-01-18 16:40:08 -0800369 log_info("[%d]begin", avsync->session_id);
370 if (avsync->state != AV_SYNC_STAT_INIT) {
371 if (avsync->type == AV_SYNC_TYPE_VIDEO)
372 internal_stop(avsync);
Song Zhaoc03ba122020-12-23 21:54:02 -0800373
Song Zhaoea5a0412021-01-18 16:40:08 -0800374 avsync->quit_poll = true;
375 if (avsync->poll_thread) {
376 pthread_join(avsync->poll_thread, NULL);
377 avsync->poll_thread = 0;
378 }
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700379 if (avsync->type == AV_SYNC_TYPE_AUDIO)
380 trigger_audio_start_cb(avsync, AV_SYNC_ASCB_STOP);
Song Zhaoaf368d52021-02-17 17:53:45 -0800381 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800382
Song Zhaoea5a0412021-01-18 16:40:08 -0800383 if (avsync->session_started) {
384 if (avsync->type == AV_SYNC_TYPE_VIDEO)
385 msync_session_set_video_stop(avsync->fd);
386 else
387 msync_session_set_audio_stop(avsync->fd);
388 }
wei.dubcc2ed22021-05-19 07:16:10 -0400389
390 if(avsync->pcr_monitor)
391 pcr_monitor_destroy(avsync->pcr_monitor);
392
Song Zhaoea5a0412021-01-18 16:40:08 -0800393 close(avsync->fd);
Song Zhaoc03ba122020-12-23 21:54:02 -0800394 pthread_mutex_destroy(&avsync->lock);
Song Zhaoea5a0412021-01-18 16:40:08 -0800395 if (avsync->type == AV_SYNC_TYPE_VIDEO) {
396 destroy_q(avsync->frame_q);
397 destroy_pattern_detector(avsync->pattern_detector);
398 }
399 log_info("[%d]done", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800400 free(avsync);
Song Zhaoea5a0412021-01-18 16:40:08 -0800401}
402
403int avs_sync_set_start_policy(void *sync, enum sync_start_policy policy)
404{
405 struct av_sync_session *avsync = (struct av_sync_session *)sync;
406
407 if (!avsync || !avsync->fd)
408 return -1;
409
410 log_info("[%d]policy %u --> %u", avsync->start_policy, policy);
411 avsync->start_policy = policy;
412 /* v_peek will be handled by libamlavsync */
413 if (policy != AV_SYNC_START_NONE &&
414 policy != AV_SYNC_START_V_PEEK)
415 return msync_session_set_start_policy(avsync->fd, policy);
416
417 return 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800418}
419
420int av_sync_pause(void *sync, bool pause)
421{
422 struct av_sync_session *avsync = (struct av_sync_session *)sync;
yongchun.li107a6162021-05-05 02:38:57 -0700423 bool v_active, a_active, v_timeout;
Song Zhaoea5a0412021-01-18 16:40:08 -0800424 int rc;
Song Zhaoc03ba122020-12-23 21:54:02 -0800425
426 if (!avsync)
427 return -1;
428
Song Zhaoea5a0412021-01-18 16:40:08 -0800429 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER)
430 return -1;
Song Zhaoc03ba122020-12-23 21:54:02 -0800431
yongchun.li107a6162021-05-05 02:38:57 -0700432 rc = msync_session_get_stat(avsync->fd, &avsync->active_mode,
433 &v_active, &a_active, &v_timeout,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700434 &avsync->in_audio_switch, SRC_A);
yongchun.li107a6162021-05-05 02:38:57 -0700435
yongchun.li5f52fb02021-06-04 18:13:05 -0700436 /* ignore only when video try to pause when audio is acive, on which
437 the control of the STC will be relays.
438 When resume,it can do always as it is possible that video just
439 paused earlier without audio yet,then audio added later before resume.
440 We shall not igore that otherwise it could cause video freeze. */
441 if (avsync->mode == AV_SYNC_MODE_AMASTER &&
442 avsync->type == AV_SYNC_TYPE_VIDEO &&
443 a_active &&
444 !avsync->in_audio_switch) {
445 if (!pause) {
446 log_info("[%d] clear video pause when audio active",
447 avsync->session_id);
448 avsync->paused = pause;
449 } else {
450 log_info("[%d] ignore the pause from video when audio active",
451 avsync->session_id);
452 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800453 return 0;
yongchun.li5f52fb02021-06-04 18:13:05 -0700454 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800455
yongchun.li107a6162021-05-05 02:38:57 -0700456 if (avsync->in_audio_switch && avsync->type == AV_SYNC_TYPE_AUDIO) {
457 log_info("[%d] ignore the pause from audio", avsync->session_id);
458 avsync->audio_switch_state = AUDIO_SWITCH_STAT_RESET;
459 return 0;
460 }
461
Song Zhaoea5a0412021-01-18 16:40:08 -0800462 rc = msync_session_set_pause(avsync->fd, pause);
Song Zhaoc03ba122020-12-23 21:54:02 -0800463 avsync->paused = pause;
Song Zhaoea5a0412021-01-18 16:40:08 -0800464 log_info("[%d]paused:%d type:%d rc %d",
465 avsync->session_id, pause, avsync->type, rc);
Song Zhaoc03ba122020-12-23 21:54:02 -0800466
Song Zhaoea5a0412021-01-18 16:40:08 -0800467 return rc;
Song Zhaoc03ba122020-12-23 21:54:02 -0800468}
469
470int av_sync_push_frame(void *sync , struct vframe *frame)
471{
472 int ret;
473 struct vframe *prev;
474 struct av_sync_session *avsync = (struct av_sync_session *)sync;
475
476 if (!avsync)
477 return -1;
478
Song Zhaoea5a0412021-01-18 16:40:08 -0800479 if (!avsync->frame_q) {
480 /* policy should be final now */
481 if (msync_session_get_start_policy(avsync->fd, &avsync->start_policy)) {
482 log_error("[%d]get policy", avsync->session_id);
483 return -1;
484 }
485
486 avsync->frame_q = create_q(MAX_FRAME_NUM);
487 if (!avsync->frame_q) {
488 log_error("[%d]create queue fail", avsync->session_id);
489 return -1;
490 }
491
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700492 /* for debugging */
493 {
Song Zhaoea5a0412021-01-18 16:40:08 -0800494 int ret;
495
496 ret = pthread_create(&avsync->poll_thread, NULL, poll_thread, avsync);
497 if (ret) {
498 log_error("[%d]create poll thread errno %d", avsync->session_id, errno);
499 destroy_q(avsync->frame_q);
500 return -1;
501 }
502 }
503 }
504
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700505 if (avsync->last_q_pts != -1) {
506 if (avsync->last_q_pts == frame->pts && avsync->mode == AV_SYNC_MODE_AMASTER) {
507 /* TODO: wrong, should remove from back of queue */
Song Zhaoc03ba122020-12-23 21:54:02 -0800508 dqueue_item(avsync->frame_q, (void **)&prev);
509 prev->free(prev);
Song Zhaoea5a0412021-01-18 16:40:08 -0800510 log_info ("[%d]drop frame with same pts %u", avsync->session_id, frame->pts);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700511 } else if (avsync->fps_cnt < 100) {
512 int32_t interval = frame->pts - avsync->last_q_pts;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700513
514 if (interval > 0 && interval <= 4500) {
515 if (avsync->fps_interval_acc == -1) {
516 avsync->fps_interval_acc = interval;
517 avsync->fps_cnt = 1;
518 } else {
519 avsync->fps_interval_acc += interval;
520 avsync->fps_cnt++;
521 avsync->fps_interval = avsync->fps_interval_acc / avsync->fps_cnt;
522 if (avsync->fps_cnt == 100)
523 log_info("[%d] fps_interval = %d", avsync->session_id, avsync->fps_interval);
524 }
525 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800526 }
527 }
528
Song Zhao065800e2021-05-26 15:56:06 -0700529 if (frame->duration == -1)
530 frame->duration = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800531 frame->hold_period = 0;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700532 avsync->last_q_pts = frame->pts;
Song Zhaoc03ba122020-12-23 21:54:02 -0800533 ret = queue_item(avsync->frame_q, frame);
534 if (avsync->state == AV_SYNC_STAT_INIT &&
535 queue_size(avsync->frame_q) >= avsync->start_thres) {
536 avsync->state = AV_SYNC_STAT_RUNNING;
Song Zhaoea5a0412021-01-18 16:40:08 -0800537 log_info("[%d]state: init --> running", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800538 }
539
540 if (ret)
541 log_error("%s queue fail:%d", ret);
Song Zhaoea5a0412021-01-18 16:40:08 -0800542 log_debug("[%d]push %u", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800543 return ret;
544
545}
546
547struct vframe *av_sync_pop_frame(void *sync)
548{
Song Zhaoea5a0412021-01-18 16:40:08 -0800549 struct vframe *frame = NULL, *enter_last_frame = NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800550 struct av_sync_session *avsync = (struct av_sync_session *)sync;
551 int toggle_cnt = 0;
552 uint32_t systime;
Song Zhao468fd652021-01-15 22:13:04 -0800553 bool pause_pts_reached = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800554 uint32_t interval;
Song Zhaoc03ba122020-12-23 21:54:02 -0800555
556 pthread_mutex_lock(&avsync->lock);
557 if (avsync->state == AV_SYNC_STAT_INIT) {
Song Zhaod62bb392021-04-23 12:25:49 -0700558 log_info("[%d]in state INIT", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800559 goto exit;
560 }
561
Song Zhaoea5a0412021-01-18 16:40:08 -0800562 if (!avsync->session_started) {
Song Zhao35a82df2021-04-15 10:58:49 -0700563 uint32_t pts;
564
Song Zhaoc03ba122020-12-23 21:54:02 -0800565 if (peek_item(avsync->frame_q, (void **)&frame, 0) || !frame) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800566 log_info("[%d]empty q", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800567 goto exit;
568 }
Song Zhao35a82df2021-04-15 10:58:49 -0700569 msync_session_get_wall(avsync->fd, &systime, &interval);
570 pts = frame->pts - avsync->delay * interval;
571 msync_session_set_video_start(avsync->fd, pts);
Song Zhaoea5a0412021-01-18 16:40:08 -0800572 avsync->session_started = true;
Song Zhao35a82df2021-04-15 10:58:49 -0700573 log_info("[%d]video start %u", avsync->session_id, pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800574 }
575
Song Zhaoea5a0412021-01-18 16:40:08 -0800576 if (avsync->start_policy == AV_SYNC_START_ALIGN &&
Song Zhaod4109b62021-04-30 08:47:17 -0700577 !avsync->first_frame_toggled &&
578 !msync_clock_started(avsync->fd)) {
579 pthread_mutex_unlock(&avsync->lock);
Song Zhaoea5a0412021-01-18 16:40:08 -0800580 log_trace("[%d]clock not started", avsync->session_id);
581 return NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800582 }
583
Song Zhaoea5a0412021-01-18 16:40:08 -0800584 enter_last_frame = avsync->last_frame;
585 msync_session_get_wall(avsync->fd, &systime, &interval);
586
587 /* handle refresh rate change */
588 if (avsync->vsync_interval == AV_SYNC_INVALID_PAUSE_PTS ||
589 avsync->vsync_interval != interval) {
590 log_info("[%d]vsync interval update %d --> %u",
591 avsync->session_id, avsync->vsync_interval, interval);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700592 if (avsync->fps_interval == -1)
593 avsync->fps_interval = interval;
Song Zhaoea5a0412021-01-18 16:40:08 -0800594 avsync->vsync_interval = interval;
595 avsync->phase_set = false;
596 reset_pattern(avsync->pattern_detector);
597 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800598 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
599 struct vframe *next_frame = NULL;
600
601 peek_item(avsync->frame_q, (void **)&next_frame, 1);
602 if (next_frame)
Song Zhaof46932e2021-05-21 01:51:45 -0700603 log_debug("[%d]cur_f %u next_f %u size %d",
604 avsync->session_id, frame->pts, next_frame->pts, queue_size(avsync->frame_q));
Song Zhaoea5a0412021-01-18 16:40:08 -0800605 if (frame_expire(avsync, systime, interval,
606 frame, next_frame, toggle_cnt)) {
607 log_debug("[%d]cur_f %u expire", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800608 toggle_cnt++;
609
Song Zhao35a82df2021-04-15 10:58:49 -0700610 if (pattern_detect(avsync,
Song Zhaoc03ba122020-12-23 21:54:02 -0800611 (avsync->last_frame?avsync->last_frame->hold_period:0),
Song Zhao35a82df2021-04-15 10:58:49 -0700612 avsync->last_holding_peroid))
613 log_info("[%d] %u break the pattern", avsync->session_id, avsync->last_frame->pts);
614
Song Zhaoc03ba122020-12-23 21:54:02 -0800615 if (avsync->last_frame)
616 avsync->last_holding_peroid = avsync->last_frame->hold_period;
617
618 dqueue_item(avsync->frame_q, (void **)&frame);
619 if (avsync->last_frame) {
620 /* free frame that are not for display */
Song Zhaoea5a0412021-01-18 16:40:08 -0800621 if (toggle_cnt > 1) {
Song Zhao35a82df2021-04-15 10:58:49 -0700622 log_debug("[%d]free %u cur %u system/d %u/%u", avsync->session_id,
623 avsync->last_frame->pts, frame->pts, systime, systime - avsync->last_poptime);
Song Zhaoc03ba122020-12-23 21:54:02 -0800624 avsync->last_frame->free(avsync->last_frame);
Song Zhaoea5a0412021-01-18 16:40:08 -0800625 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800626 } else {
627 avsync->first_frame_toggled = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800628 log_info("[%d]first frame %u", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800629 }
630 avsync->last_frame = frame;
Song Zhao5d2b4772021-01-18 16:40:08 -0800631 avsync->last_pts = frame->pts;
Song Zhaoc03ba122020-12-23 21:54:02 -0800632 } else
633 break;
634 }
635
636 /* pause pts */
637 if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS && avsync->last_frame) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800638 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
Song Zhao468fd652021-01-15 22:13:04 -0800639 pause_pts_reached = true;
Song Zhaoc03ba122020-12-23 21:54:02 -0800640 else
Song Zhao468fd652021-01-15 22:13:04 -0800641 pause_pts_reached = (int)(avsync->last_frame->pts - avsync->pause_pts) >= 0;
642 } else if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS) {
643 if (!peek_item(avsync->frame_q, (void **)&frame, 0))
644 pause_pts_reached = (int)(frame->pts - avsync->pause_pts) >= 0;
645 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800646
Song Zhao468fd652021-01-15 22:13:04 -0800647 if (pause_pts_reached) {
648 if (avsync->pause_pts_cb)
649 avsync->pause_pts_cb(avsync->pause_pts,
Song Zhaoc03ba122020-12-23 21:54:02 -0800650 avsync->pause_cb_priv);
651
Song Zhao468fd652021-01-15 22:13:04 -0800652 /* stay in paused until av_sync_pause(false) */
653 avsync->paused = true;
654 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
Song Zhaoea5a0412021-01-18 16:40:08 -0800655 log_info ("[%d]reach pause pts: %u",
656 avsync->session_id, avsync->last_frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800657 }
658
659exit:
660 pthread_mutex_unlock(&avsync->lock);
661 if (avsync->last_frame) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800662 if (enter_last_frame != avsync->last_frame)
663 log_debug("[%d]pop %u", avsync->session_id, avsync->last_frame->pts);
Song Zhao35a82df2021-04-15 10:58:49 -0700664 log_trace("[%d]pop %u", avsync->session_id, avsync->last_frame->pts);
Song Zhao065800e2021-05-26 15:56:06 -0700665 /* don't update vpts for out_lier */
666 if (avsync->last_frame->duration != -1)
667 msync_session_update_vpts(avsync->fd, systime,
668 avsync->last_frame->pts, interval * avsync->delay);
Song Zhaoc03ba122020-12-23 21:54:02 -0800669 } else
Song Zhaoea5a0412021-01-18 16:40:08 -0800670 if (enter_last_frame != avsync->last_frame)
671 log_debug("[%d]pop (nil)", avsync->session_id);
672
Song Zhao35a82df2021-04-15 10:58:49 -0700673 avsync->last_poptime = systime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800674 if (avsync->last_frame)
675 avsync->last_frame->hold_period++;
676 return avsync->last_frame;
677}
678
Song Zhaoc03ba122020-12-23 21:54:02 -0800679static inline uint32_t abs_diff(uint32_t a, uint32_t b)
680{
Song Zhaoea5a0412021-01-18 16:40:08 -0800681 return (int)(a - b) > 0 ? a - b : b - a;
Song Zhaoc03ba122020-12-23 21:54:02 -0800682}
683
684static uint64_t time_diff (struct timeval *b, struct timeval *a)
685{
686 return (b->tv_sec - a->tv_sec)*1000000 + (b->tv_usec - a->tv_usec);
687}
688
Song Zhaoc03ba122020-12-23 21:54:02 -0800689static bool frame_expire(struct av_sync_session* avsync,
690 uint32_t systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800691 uint32_t interval,
Song Zhaoc03ba122020-12-23 21:54:02 -0800692 struct vframe * frame,
693 struct vframe * next_frame,
694 int toggle_cnt)
695{
696 uint32_t fpts = frame->pts;
697 bool expire = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800698 uint32_t pts_correction = avsync->delay * interval;
Song Zhaoc03ba122020-12-23 21:54:02 -0800699
700 if (avsync->paused && avsync->pause_pts == AV_SYNC_INVALID_PAUSE_PTS)
701 return false;
702
703 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
704 return true;
705
Song Zhaoe0bf6ad2021-07-09 11:28:42 -0700706 if (avsync->mode == AV_SYNC_MODE_FREE_RUN) {
707 /* render according to FPS */
708 if (!VALID_TS(avsync->last_r_syst) ||
709 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
710 avsync->last_r_syst = systime;
711 return true;
712 }
713 return false;
714 }
715
Song Zhaoc03ba122020-12-23 21:54:02 -0800716 if (!fpts) {
717 if (avsync->last_frame) {
718 /* try to accumulate duration as PTS */
719 fpts = avsync->vpts + avsync->last_frame->duration;
720 } else {
721 fpts = avsync->vpts;
722 }
723 }
724 systime += pts_correction;
725
726 /* phase adjustment */
727 if (avsync->phase_set)
728 systime += avsync->phase;
729
Song Zhao35a82df2021-04-15 10:58:49 -0700730 log_trace("[%d]systime:%u phase:%u correct:%u fpts:%u",
Song Zhaoea5a0412021-01-18 16:40:08 -0800731 avsync->session_id, systime,
Song Zhao35a82df2021-04-15 10:58:49 -0700732 avsync->phase_set?avsync->phase:0, pts_correction, fpts);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700733 if (abs_diff(systime, fpts) > avsync->disc_thres_min) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800734 /* ignore discontinity under pause */
Song Zhaoea5a0412021-01-18 16:40:08 -0800735 if (avsync->paused)
Song Zhaoc03ba122020-12-23 21:54:02 -0800736 return false;
737
Song Zhaoa2985cb2021-06-24 12:01:47 -0700738 if ((VALID_TS(avsync->last_log_syst) && avsync->last_log_syst != systime) ||
739 (VALID_TS(avsync->last_pts) && avsync->last_pts != fpts)) {
Song Zhao5d2b4772021-01-18 16:40:08 -0800740 struct timeval now;
741
742 gettimeofday(&now, NULL);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700743 avsync->last_log_syst = systime;
Song Zhao5d2b4772021-01-18 16:40:08 -0800744 avsync->last_pts = fpts;
745 if (time_diff(&now, &avsync->sync_lost_print_time) >=
746 SYNC_LOST_PRINT_THRESHOLD) {
Song Zhaof46932e2021-05-21 01:51:45 -0700747 log_warn("[%d]sync lost systime:%u fpts:%u lost:%u",
Song Zhaoea5a0412021-01-18 16:40:08 -0800748 avsync->session_id, systime, fpts, avsync->sync_lost_cnt);
Song Zhao5d2b4772021-01-18 16:40:08 -0800749 avsync->sync_lost_cnt = 0;
Song Zhaobc6161d2021-03-08 09:59:33 -0800750 gettimeofday(&avsync->sync_lost_print_time, NULL);
Song Zhao5d2b4772021-01-18 16:40:08 -0800751 } else
752 avsync->sync_lost_cnt++;
753 }
Song Zhaod62bb392021-04-23 12:25:49 -0700754
755 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP &&
756 LIVE_MODE(avsync->mode) &&
Song Zhaoa2985cb2021-06-24 12:01:47 -0700757 VALID_TS(avsync->last_pts) &&
Song Zhao065800e2021-05-26 15:56:06 -0700758 abs_diff(avsync->last_pts, fpts) > STREAM_DISC_THRES) {
Song Zhaod62bb392021-04-23 12:25:49 -0700759 /* outlier by stream error */
760 avsync->outlier_cnt++;
Song Zhao065800e2021-05-26 15:56:06 -0700761 frame->duration = -1;
Song Zhaod62bb392021-04-23 12:25:49 -0700762 if (avsync->outlier_cnt < OUTLIER_MAX_CNT) {
763 log_info("render outlier %u", fpts);
764 return true;
765 }
766 }
767
768 avsync->outlier_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800769 avsync->state = AV_SYNC_STAT_SYNC_LOST;
770 avsync->phase_set = false;
Song Zhaoa58c3e92021-03-09 18:52:55 -0800771 reset_pattern(avsync->pattern_detector);
Song Zhaoa2985cb2021-06-24 12:01:47 -0700772
773 if (LIVE_MODE(avsync->mode) && avsync->last_disc_pts != fpts) {
Song Zhaod62bb392021-04-23 12:25:49 -0700774 log_info ("[%d]video disc %u --> %u",
Song Zhaoa2985cb2021-06-24 12:01:47 -0700775 avsync->session_id, systime, fpts);
Song Zhao409739b2021-05-12 22:21:40 -0700776 msync_session_set_video_dis(avsync->fd, fpts);
777 avsync->last_disc_pts = fpts;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700778 }
779
780 if ((int)(systime - fpts) > 0) {
781 if ((int)(systime - fpts) < avsync->disc_thres_max) {
782 /* catch up PCR */
Song Zhaof46932e2021-05-21 01:51:45 -0700783 return true;
Song Zhaoa2985cb2021-06-24 12:01:47 -0700784 } else {
785 /* render according to FPS */
786 if (!VALID_TS(avsync->last_r_syst) ||
787 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
788 avsync->last_r_syst = systime;
789 return true;
790 }
791 return false;
792 }
793 } else if (LIVE_MODE(avsync->mode)) {
794 /* hold if the gap is small */
795 if ((int)(fpts - systime) < avsync->disc_thres_max) {
796 return false;
797 } else {
798 /* render according to FPS */
799 if (!VALID_TS(avsync->last_r_syst) ||
800 (int)(systime - avsync->last_r_syst) >= avsync->fps_interval) {
801 avsync->last_r_syst = systime;
802 return true;
803 }
804 return false;
805 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800806 }
807 }
808
Song Zhao52f55192021-05-06 10:52:21 -0700809 /* In some cases, keeping pattern will enlarge the gap */
810 if (abs_diff(systime, fpts) > AV_PATTERN_RESET_THRES &&
811 avsync->first_frame_toggled) {
812 reset_pattern(avsync->pattern_detector);
Song Zhaof46932e2021-05-21 01:51:45 -0700813 log_warn("sync pattern reset sys:%u fpts:%u",
Song Zhao52f55192021-05-06 10:52:21 -0700814 systime, fpts);
815 }
816
Song Zhaoc03ba122020-12-23 21:54:02 -0800817 expire = (int)(systime - fpts) >= 0;
818
819 /* scatter the frame in different vsync whenever possible */
820 if (expire && next_frame && next_frame->pts && toggle_cnt) {
821 /* multi frame expired in current vsync but no frame in next vsync */
Song Zhaoea5a0412021-01-18 16:40:08 -0800822 if (systime + interval < next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800823 expire = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800824 log_debug("[%d]unset expire systime:%d inter:%d next_pts:%d toggle_cnt:%d",
825 avsync->session_id, systime, interval, next_frame->pts, toggle_cnt);
Song Zhaoc03ba122020-12-23 21:54:02 -0800826 }
827 } else if (!expire && next_frame && next_frame->pts && !toggle_cnt
828 && avsync->first_frame_toggled) {
829 /* next vsync will have at least 2 frame expired */
Song Zhao35a82df2021-04-15 10:58:49 -0700830 if (systime + interval >= next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800831 expire = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800832 log_debug("[%d]set expire systime:%d inter:%d next_pts:%d",
833 avsync->session_id, systime, interval, next_frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800834 }
835 }
836
Song Zhaoa58c3e92021-03-09 18:52:55 -0800837 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP)
838 correct_pattern(avsync->pattern_detector, frame, next_frame,
839 (avsync->last_frame?avsync->last_frame->hold_period:0),
840 avsync->last_holding_peroid, systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800841 interval, &expire);
Song Zhaoc03ba122020-12-23 21:54:02 -0800842
843 if (expire) {
844 avsync->vpts = fpts;
845 /* phase adjustment */
846 if (!avsync->phase_set) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800847 uint32_t phase_thres = interval / 4;
Song Zhaoc03ba122020-12-23 21:54:02 -0800848 if ( systime > fpts && (systime - fpts) < phase_thres) {
849 /* too aligned to current VSYNC, separate them to 1/4 VSYNC */
850 avsync->phase += phase_thres - (systime - fpts);
851 avsync->phase_set = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800852 log_info("[%d]adjust phase to %d", avsync->session_id, avsync->phase);
Song Zhaoc03ba122020-12-23 21:54:02 -0800853 }
854 if (!avsync->phase_set && systime > fpts &&
Song Zhaoea5a0412021-01-18 16:40:08 -0800855 systime < (fpts + interval) &&
856 (systime - fpts) > interval - phase_thres) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800857 /* too aligned to previous VSYNC, separate them to 1/4 VSYNC */
Song Zhaoea5a0412021-01-18 16:40:08 -0800858 avsync->phase += phase_thres + fpts + interval - systime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800859 avsync->phase_set = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800860 log_info("[%d]adjust phase to %d", avsync->session_id, avsync->phase);
Song Zhaoc03ba122020-12-23 21:54:02 -0800861 }
862 }
863
864 if (avsync->state != AV_SYNC_STAT_SYNC_SETUP)
Song Zhaoea5a0412021-01-18 16:40:08 -0800865 log_info("[%d]sync setup", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800866 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhao5d2b4772021-01-18 16:40:08 -0800867 avsync->sync_lost_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800868 }
869 return expire;
870}
871
Song Zhao35a82df2021-04-15 10:58:49 -0700872static bool pattern_detect(struct av_sync_session* avsync, int cur_period, int last_period)
Song Zhaoc03ba122020-12-23 21:54:02 -0800873{
Song Zhao35a82df2021-04-15 10:58:49 -0700874 bool ret = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800875 log_trace("[%d]cur_period: %d last_period: %d",
876 avsync->session_id, cur_period, last_period);
Song Zhao35a82df2021-04-15 10:58:49 -0700877 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P32, cur_period, last_period))
878 ret = true;
879 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P22, cur_period, last_period))
880 ret = true;
881 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P41, cur_period, last_period))
882 ret = true;
883 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P11, cur_period, last_period))
884 ret = true;
885
886 return ret;
Song Zhaoc03ba122020-12-23 21:54:02 -0800887}
888
889int av_sync_set_speed(void *sync, float speed)
890{
891 struct av_sync_session *avsync = (struct av_sync_session *)sync;
892
893 if (speed < 0.001f || speed > 100) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800894 log_error("[%d]wrong speed %f [0.0001, 100]", avsync->session_id, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -0800895 return -1;
896 }
897
Song Zhaoea5a0412021-01-18 16:40:08 -0800898 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER ||
899 avsync->mode == AV_SYNC_MODE_IPTV) {
900 log_info("[%d]ignore set speed in mode %d", avsync->session_id, avsync->mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800901 return 0;
Song Zhaoea5a0412021-01-18 16:40:08 -0800902 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800903
Song Zhaoea5a0412021-01-18 16:40:08 -0800904 avsync->speed = speed;
905
906 if (avsync->type == AV_SYNC_TYPE_AUDIO) {
907 if (speed == 1.0) {
908 avsync->mode = avsync->backup_mode;
909 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
910 } else {
911 avsync->backup_mode = avsync->mode;
912 avsync->mode = AV_SYNC_MODE_FREE_RUN;
913 log_info("[%d]audio to freerun mode", avsync->session_id);
914 }
915 }
916#if 0
Song Zhaoc03ba122020-12-23 21:54:02 -0800917 if (avsync->mode != AV_SYNC_MODE_VMASTER) {
918 log_info("ignore set speed in mode %d", avsync->mode);
919 return 0;
920 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800921#endif
Song Zhaoc03ba122020-12-23 21:54:02 -0800922
Song Zhaoea5a0412021-01-18 16:40:08 -0800923 log_info("session[%d] set rate to %f", avsync->session_id, speed);
924 return msync_session_set_rate(avsync->fd, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -0800925}
926
927int av_sync_change_mode(void *sync, enum sync_mode mode)
928{
929 struct av_sync_session *avsync = (struct av_sync_session *)sync;
930
931 if (!avsync)
932 return -1;
933
Song Zhaoea5a0412021-01-18 16:40:08 -0800934 if (msync_session_set_mode(avsync->fd, mode)) {
935 log_error("[%d]fail to set mode %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800936 return -1;
937 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800938 avsync->mode = mode;
Song Zhaoea5a0412021-01-18 16:40:08 -0800939 log_info("[%d]update sync mode to %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800940 return 0;
941}
942
Song Zhao01031bb2021-05-13 21:23:20 -0700943int av_sync_get_mode(void *sync, enum sync_mode *mode)
944{
945 struct av_sync_session *avsync = (struct av_sync_session *)sync;
946
947 if (!avsync || !mode)
948 return -1;
949
950 *mode = avsync->mode;
951 return 0;
952}
953
Song Zhaoc03ba122020-12-23 21:54:02 -0800954int av_sync_set_pause_pts(void *sync, pts90K pts)
955{
956 struct av_sync_session *avsync = (struct av_sync_session *)sync;
957
958 if (!avsync)
959 return -1;
960
961 avsync->pause_pts = pts;
Song Zhaoea5a0412021-01-18 16:40:08 -0800962 log_info("[%d]set pause pts: %u", avsync->session_id, pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800963 return 0;
964}
965
966int av_sync_set_pause_pts_cb(void *sync, pause_pts_done cb, void *priv)
967{
968 struct av_sync_session *avsync = (struct av_sync_session *)sync;
969
970 if (!avsync)
971 return -1;
972
973 avsync->pause_pts_cb = cb;
974 avsync->pause_cb_priv = priv;
975 return 0;
976}
Song Zhaoea5a0412021-01-18 16:40:08 -0800977
978static void trigger_audio_start_cb(struct av_sync_session *avsync,
979 avs_ascb_reason reason)
980{
981 if (avsync) {
982 pthread_mutex_lock(&avsync->lock);
983 if (avsync->audio_start) {
984 avsync->audio_start(avsync->audio_start_priv, reason);
985 avsync->session_started = true;
986 avsync->audio_start = NULL;
987 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
988 }
989 pthread_mutex_unlock(&avsync->lock);
990 }
991}
992
993avs_start_ret av_sync_audio_start(
994 void *sync,
995 pts90K pts,
996 pts90K delay,
997 audio_start_cb cb,
998 void *priv)
999{
1000 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1001 uint32_t start_mode;
yongchun.li59e873d2021-07-07 11:42:38 -07001002 uint32_t systime;
Song Zhaoea5a0412021-01-18 16:40:08 -08001003 avs_start_ret ret = AV_SYNC_ASTART_ERR;
1004 bool create_poll_t = false;
1005
1006 if (!avsync)
1007 return ret;
1008
yongchun.li59e873d2021-07-07 11:42:38 -07001009 log_info("%d av_sync_audio_start pts(ms) %d delay %d ms",
1010 avsync->session_id, (int)pts/90, (int)delay/90);
Song Zhaoea5a0412021-01-18 16:40:08 -08001011
yongchun.li59e873d2021-07-07 11:42:38 -07001012 if (avsync->in_audio_switch &&
1013 avsync->audio_switch_state == AUDIO_SWITCH_STAT_AGAIN)
1014 {
1015 start_mode = AVS_START_SYNC;
1016 log_info("%d AUDIO_SWITCH_STAT_AGAIN", avsync->session_id);
1017 } else {
1018 if (msync_session_set_audio_start(avsync->fd, pts, delay, &start_mode))
1019 log_error("[%d]fail to set audio start", avsync->session_id);
1020 }
1021 if (avsync->in_audio_switch &&
1022 (avsync->audio_switch_state == AUDIO_SWITCH_STAT_RESET ||
1023 avsync->audio_switch_state == AUDIO_SWITCH_STAT_AGAIN)) {
1024 msync_session_get_wall(avsync->fd, &systime, NULL);
1025 if ((int)(systime - pts) > A_ADJ_THREDHOLD_LB &&
1026 start_mode == AVS_START_SYNC) {
1027 log_info("%d audio_switch audio need drop first.ahead %d ms",
1028 avsync->session_id, (int)(systime - pts)/90);
1029 ret = AV_SYNC_ASTART_AGAIN;
1030 avsync->audio_switch_state = AUDIO_SWITCH_STAT_AGAIN;
1031 goto exit;
1032 }
1033 else {
1034 int diff = (int)(pts - systime);
1035 log_info("%d audio_switch_state to start mode %d diff %d ms",
1036 avsync->session_id, start_mode, diff/90);
1037 avsync->audio_switch_state = AUDIO_SWITCH_STAT_START;
1038 if (diff < A_ADJ_THREDHOLD_LB) {
1039 log_info("%d orig mode %d already close enough direct start",
1040 avsync->session_id, start_mode);
1041 start_mode = AVS_START_SYNC;
1042 }
1043 }
yongchun.li107a6162021-05-05 02:38:57 -07001044 }
1045
Song Zhaoea5a0412021-01-18 16:40:08 -08001046 if (start_mode == AVS_START_SYNC) {
1047 ret = AV_SYNC_ASTART_SYNC;
1048 avsync->session_started = true;
Song Zhao065800e2021-05-26 15:56:06 -07001049 avsync->state = AV_SYNC_STAT_RUNNING;
Song Zhaod62bb392021-04-23 12:25:49 -07001050 } else if (start_mode == AVS_START_ASYNC) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001051 ret = AV_SYNC_ASTART_ASYNC;
Song Zhaod62bb392021-04-23 12:25:49 -07001052 avsync->state = AV_SYNC_STAT_RUNNING;
1053 } else if (start_mode == AVS_START_AGAIN) {
1054 ret = AV_SYNC_ASTART_AGAIN;
1055 }
1056
1057 if (ret == AV_SYNC_ASTART_AGAIN)
1058 goto exit;
Song Zhaoea5a0412021-01-18 16:40:08 -08001059
yongchun.li107a6162021-05-05 02:38:57 -07001060 if (avsync->mode == AV_SYNC_MODE_AMASTER || avsync->in_audio_switch) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001061 create_poll_t = true;
1062 if (start_mode == AVS_START_ASYNC) {
1063 if (!cb) {
1064 log_error("[%d]invalid cb", avsync->session_id);
1065 return AV_SYNC_ASTART_ERR;
1066 }
1067 avsync->audio_start = cb;
1068 avsync->audio_start_priv = priv;
1069 }
Song Zhaod62bb392021-04-23 12:25:49 -07001070 } else if (LIVE_MODE(avsync->mode))
Song Zhaoea5a0412021-01-18 16:40:08 -08001071 create_poll_t = true;
1072
Song Zhaod62bb392021-04-23 12:25:49 -07001073 if (create_poll_t && !avsync->poll_thread) {
Song Zhaoea5a0412021-01-18 16:40:08 -08001074 int ret;
1075
1076 log_info("[%d]start poll thread", avsync->session_id);
1077 avsync->quit_poll = false;
1078 ret = pthread_create(&avsync->poll_thread, NULL, poll_thread, avsync);
1079 if (ret) {
1080 log_error("[%d]create poll thread errno %d", avsync->session_id, errno);
1081 return AV_SYNC_ASTART_ERR;
1082 }
1083 }
Song Zhaod62bb392021-04-23 12:25:49 -07001084 if (LIVE_MODE(avsync->mode)) {
Song Zhaod62bb392021-04-23 12:25:49 -07001085 msync_session_get_wall(avsync->fd, &systime, NULL);
1086 log_info("[%d]return %u w %u pts %u d %u",
1087 avsync->session_id, ret, systime, pts, delay);
1088 }
1089exit:
Song Zhaoea5a0412021-01-18 16:40:08 -08001090 log_info("[%d]return %u", avsync->session_id, ret);
1091 return ret;
1092}
1093
1094int av_sync_audio_render(
1095 void *sync,
1096 pts90K pts,
1097 struct audio_policy *policy)
1098{
1099 int ret = 0;
Song Zhao065800e2021-05-26 15:56:06 -07001100 bool out_lier = false;
Song Zhaoea5a0412021-01-18 16:40:08 -08001101 uint32_t systime;
1102 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1103 avs_audio_action action = AA_SYNC_AA_MAX;
1104
1105 if (!avsync || !policy)
1106 return -1;
1107
yongchun.li107a6162021-05-05 02:38:57 -07001108 msync_session_get_wall(avsync->fd, &systime, NULL);
1109
1110 log_trace("audio render pts %u, systime %u, mode %u diff ms %d",
1111 pts, systime, avsync->mode, (int)(pts-systime)/90);
1112
1113 if (avsync->in_audio_switch
1114 && avsync->audio_switch_state == AUDIO_SWITCH_STAT_START) {
1115 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_HB) {
1116 log_info("Audio pts in system range sys %u pts %u\n", systime, pts);
1117 avsync->audio_switch_state = AUDIO_SWITCH_STAT_FINISH;
1118 action = AV_SYNC_AA_RENDER;
1119 } else if ((int)(systime - pts) > 0) {
1120 log_info("[%d] audio change drop %d ms sys %u pts %u", avsync->session_id,
1121 (int)(systime - pts)/90, systime, pts);
1122 action = AV_SYNC_AA_DROP;
1123 } else {
1124 action = AV_SYNC_AA_INSERT;
1125 log_info("[%d] audio change insert %d ms sys %u pts %u", avsync->session_id,
1126 (int)(pts - systime)/90, systime, pts);
1127 }
1128 goto done;
1129 }
1130
Song Zhaoea5a0412021-01-18 16:40:08 -08001131 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
1132 avsync->mode == AV_SYNC_MODE_AMASTER) {
1133 action = AV_SYNC_AA_RENDER;
1134 goto done;
1135 }
1136
Song Zhaod62bb392021-04-23 12:25:49 -07001137 /* stopping procedure, unblock audio rendering */
1138 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER &&
1139 avsync->active_mode == AV_SYNC_MODE_FREE_RUN) {
1140 action = AV_SYNC_AA_DROP;
1141 goto done;
1142 }
1143
Song Zhao7daf3a12021-05-10 22:22:25 -07001144 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
1145 avsync->mode == AV_SYNC_MODE_AMASTER) {
1146 action = AV_SYNC_AA_RENDER;
1147 goto done;
1148 }
1149
Song Zhaod62bb392021-04-23 12:25:49 -07001150 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP &&
1151 LIVE_MODE(avsync->mode) &&
1152 abs_diff(systime, pts) > STREAM_DISC_THRES) {
1153 /* outlier by stream error */
1154 avsync->outlier_cnt++;
1155 if (avsync->outlier_cnt > OUTLIER_MAX_CNT) {
1156 /* treat as disc, just drop current frame */
1157 avsync->state = AV_SYNC_STAT_SYNC_LOST;
1158 avsync->outlier_cnt = 0;
1159 action = AV_SYNC_AA_DROP;
1160 systime = pts;
Song Zhaod62bb392021-04-23 12:25:49 -07001161 goto done;
1162 }
1163 log_info("[%d]ignore outlier %u", avsync->session_id, pts);
1164 pts = systime;
1165 action = AV_SYNC_AA_RENDER;
Song Zhao065800e2021-05-26 15:56:06 -07001166 out_lier = true;
Song Zhaod62bb392021-04-23 12:25:49 -07001167 goto done;
1168 }
1169
1170 avsync->outlier_cnt = 0;
1171 /* low bound from sync_lost to sync_setup */
1172 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_LB) {
1173 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
1174 action = AV_SYNC_AA_RENDER;
1175 goto done;
1176 }
1177
1178 /* high bound of sync_setup */
1179 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD_HB &&
1180 avsync->state != AV_SYNC_STAT_SYNC_LOST) {
1181 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhaoea5a0412021-01-18 16:40:08 -08001182 action = AV_SYNC_AA_RENDER;
1183 goto done;
1184 }
1185
1186 if ((int)(systime - pts) > 0) {
Song Zhaod62bb392021-04-23 12:25:49 -07001187 avsync->state = AV_SYNC_STAT_SYNC_LOST;
Song Zhaoea5a0412021-01-18 16:40:08 -08001188 action = AV_SYNC_AA_DROP;
1189 goto done;
1190 }
1191
1192 if ((int)(systime - pts) < 0) {
Song Zhaod62bb392021-04-23 12:25:49 -07001193 avsync->state = AV_SYNC_STAT_SYNC_LOST;
Song Zhaoea5a0412021-01-18 16:40:08 -08001194 action = AV_SYNC_AA_INSERT;
1195 goto done;
1196 }
1197
1198done:
1199 policy->action = action;
1200 policy->delta = (int)(systime - pts);
1201 if (action == AV_SYNC_AA_RENDER) {
1202 avsync->apts = pts;
yongchun.li107a6162021-05-05 02:38:57 -07001203 if (!avsync->in_audio_switch) {
Song Zhao065800e2021-05-26 15:56:06 -07001204 if (!out_lier)
1205 msync_session_update_apts(avsync->fd, systime, pts, 0);
Song Zhaof46932e2021-05-21 01:51:45 -07001206 log_debug("[%d]return %d sys %u - pts %u = %d",
Song Zhao409739b2021-05-12 22:21:40 -07001207 avsync->session_id, action, systime, pts, systime - pts);
yongchun.li107a6162021-05-05 02:38:57 -07001208 } else if(avsync->audio_switch_state == AUDIO_SWITCH_STAT_FINISH) {
1209 msync_session_update_apts(avsync->fd, systime, pts, 0);
1210 log_info("[%d] audio switch done sys %u pts %u",
1211 avsync->session_id, systime, pts);
1212 msync_session_set_audio_switch(avsync->fd, false);
1213 avsync->in_audio_switch = false;
1214 avsync->audio_switch_state = AUDIO_SWITCH_STAT_INIT;
1215 } else {
1216 log_trace("[%d] in audio switch ret %d sys %u - pts %u = %d",
1217 avsync->session_id, action, systime, pts, systime - pts);
1218 }
Song Zhaoa2985cb2021-06-24 12:01:47 -07001219 avsync->audio_drop_cnt = 0;
Song Zhaoea5a0412021-01-18 16:40:08 -08001220 } else {
Song Zhaoa2985cb2021-06-24 12:01:47 -07001221 if (abs_diff(systime, pts) > avsync->disc_thres_min &&
yongchun.li085b5a42021-05-24 04:22:53 -07001222 avsync->last_disc_pts != pts &&
1223 !avsync->in_audio_switch) {
Song Zhao409739b2021-05-12 22:21:40 -07001224 log_info ("[%d]audio disc %u --> %u",
1225 avsync->session_id, systime, pts);
1226 msync_session_set_audio_dis(avsync->fd, pts);
1227 avsync->last_disc_pts = pts;
Song Zhaoa2985cb2021-06-24 12:01:47 -07001228 } else if (action == AV_SYNC_AA_DROP) {
1229 struct timeval now;
1230
1231 /* dropping recovery */
1232 gettimeofday(&now, NULL);
1233 if (!avsync->audio_drop_cnt)
1234 avsync->audio_drop_start = now;
1235 avsync->audio_drop_cnt++;
1236 if (time_diff(&now, &avsync->audio_drop_start) > 500000) {
1237 log_info ("[%d]audio keep dropping sys %u vs a %u",
1238 avsync->session_id, systime, pts);
1239 msync_session_set_audio_dis(avsync->fd, pts);
1240 }
Song Zhao409739b2021-05-12 22:21:40 -07001241 }
Song Zhaoa2985cb2021-06-24 12:01:47 -07001242 if (action != AV_SYNC_AA_DROP)
1243 avsync->audio_drop_cnt = 0;
Song Zhaof46932e2021-05-21 01:51:45 -07001244 log_debug("[%d]return %d sys %u - pts %u = %d",
Song Zhaod62bb392021-04-23 12:25:49 -07001245 avsync->session_id, action, systime, pts, systime - pts);
Song Zhaoea5a0412021-01-18 16:40:08 -08001246 }
1247
1248 return ret;
1249}
1250
1251int av_sync_get_clock(void *sync, pts90K *pts)
1252{
1253 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1254
1255 if (!avsync || !pts)
1256 return -1;
1257 return msync_session_get_wall(avsync->fd, pts, NULL);
1258}
1259
1260static void handle_mode_change_a(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -07001261 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -08001262{
Song Zhaoe208d692021-04-19 15:38:52 -07001263 log_info("[%d]amode %d mode %d v/a/vt %d/%d/%d", avsync->session_id,
1264 avsync->active_mode, avsync->mode, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -08001265 if (avsync->active_mode == AV_SYNC_MODE_AMASTER) {
1266 float speed;
1267 if (avsync->start_policy == AV_SYNC_START_ALIGN &&
Song Zhaoe208d692021-04-19 15:38:52 -07001268 a_active && avsync->audio_start) {
yongchun.li107a6162021-05-05 02:38:57 -07001269 if (v_active || v_timeout || avsync->in_audio_switch) {
Song Zhaoe208d692021-04-19 15:38:52 -07001270 log_info("audio start cb");
1271 trigger_audio_start_cb(avsync, AV_SYNC_ASCB_OK);
yongchun.li107a6162021-05-05 02:38:57 -07001272 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001273 }
1274
1275 if (!msync_session_get_rate(avsync->fd, &speed)) {
1276 /* speed change is triggered by asink,
1277 * attached audio HAL will handle it
1278 */
1279 if (speed != avsync->speed)
1280 log_info("[%d]new rate %f", avsync->session_id, speed);
1281 if (speed == 1.0) {
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001282 if (avsync->mode != avsync->backup_mode) {
1283 avsync->mode = avsync->backup_mode;
1284 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
1285 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001286 } else {
1287 avsync->backup_mode = avsync->mode;
1288 avsync->mode = AV_SYNC_MODE_FREE_RUN;
1289 log_info("[%d]audio to freerun mode", avsync->session_id);
1290 }
1291 avsync->speed = speed;
1292 }
Song Zhaod62bb392021-04-23 12:25:49 -07001293 } else if (avsync->active_mode == AV_SYNC_MODE_PCR_MASTER) {
1294 struct session_debug debug;
1295 if (!msync_session_get_debug_mode(avsync->fd, &debug)) {
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001296 if (debug.debug_freerun && !avsync->debug_freerun) {
Song Zhaod62bb392021-04-23 12:25:49 -07001297 avsync->backup_mode = avsync->mode;
1298 avsync->mode = AV_SYNC_MODE_FREE_RUN;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001299 avsync->debug_freerun = true;
Song Zhaod62bb392021-04-23 12:25:49 -07001300 log_warn("[%d]audio to freerun mode", avsync->session_id);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001301 } else if (!debug.debug_freerun && avsync->debug_freerun) {
Song Zhaod62bb392021-04-23 12:25:49 -07001302 avsync->mode = avsync->backup_mode;
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001303 avsync->debug_freerun = false;
Song Zhaod62bb392021-04-23 12:25:49 -07001304 log_warn("[%d]audio back to mode %d",
1305 avsync->session_id, avsync->mode);
1306 }
1307 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001308 }
1309}
1310
1311static void handle_mode_change_v(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -07001312 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -08001313{
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001314 struct session_debug debug;
1315
Song Zhaoea5a0412021-01-18 16:40:08 -08001316 log_info("[%d]amode mode %d %d v/a %d/%d", avsync->session_id,
1317 avsync->active_mode, avsync->mode, v_active, a_active);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001318 if (!msync_session_get_debug_mode(avsync->fd, &debug)) {
1319 if (debug.debug_freerun && !avsync->debug_freerun) {
1320 avsync->backup_mode = avsync->mode;
1321 avsync->mode = AV_SYNC_MODE_FREE_RUN;
1322 avsync->debug_freerun = true;
1323 log_warn("[%d]video to freerun mode", avsync->session_id);
1324 } else if (!debug.debug_freerun && avsync->debug_freerun) {
1325 avsync->mode = avsync->backup_mode;
1326 avsync->debug_freerun = false;
1327 log_warn("[%d]video back to mode %d",
1328 avsync->session_id, avsync->mode);
Song Zhaod62bb392021-04-23 12:25:49 -07001329 }
1330 }
Song Zhaoea5a0412021-01-18 16:40:08 -08001331}
1332
1333static void * poll_thread(void * arg)
1334{
1335 int ret = 0;
1336 struct av_sync_session *avsync = (struct av_sync_session *)arg;
1337 const int fd = avsync->fd;
1338 struct pollfd pfd = {
1339 /* default blocking capture */
1340 .events = POLLIN | POLLRDNORM | POLLPRI | POLLOUT | POLLWRNORM,
1341 .fd = avsync->fd,
1342 };
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001343 enum src_flag sflag = SRC_A;
Song Zhaoea5a0412021-01-18 16:40:08 -08001344
1345 prctl (PR_SET_NAME, "avs_poll");
1346 log_info("[%d]enter", avsync->session_id);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001347
1348 if (avsync->type == AV_SYNC_TYPE_AUDIO)
1349 sflag = SRC_A;
1350 else if (avsync->type == AV_SYNC_TYPE_VIDEO)
1351 sflag = SRC_V;
1352
Song Zhaoea5a0412021-01-18 16:40:08 -08001353 while (!avsync->quit_poll) {
1354 for (;;) {
1355 ret = poll(&pfd, 1, 10);
1356 if (ret > 0)
1357 break;
1358 if (avsync->quit_poll)
1359 goto exit;
1360 if (errno == EINTR)
1361 continue;
1362 }
1363
1364 /* error handling */
1365 if (pfd.revents & POLLERR)
1366 log_error("[%d]POLLERR received", avsync->session_id);
1367
Song Zhaod62bb392021-04-23 12:25:49 -07001368 /* mode change. Non-exclusive wait so all the processes
1369 * shall be woken up
1370 */
Song Zhaoea5a0412021-01-18 16:40:08 -08001371 if (pfd.revents & POLLPRI) {
Song Zhaoe208d692021-04-19 15:38:52 -07001372 bool v_active, a_active, v_timeout;
Song Zhaoea5a0412021-01-18 16:40:08 -08001373
1374 msync_session_get_stat(fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001375 &v_active, &a_active, &v_timeout, &avsync->in_audio_switch, sflag);
Song Zhaoea5a0412021-01-18 16:40:08 -08001376
1377 if (avsync->type == AV_SYNC_TYPE_AUDIO)
Song Zhaoe208d692021-04-19 15:38:52 -07001378 handle_mode_change_a(avsync, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -08001379 else if (avsync->type == AV_SYNC_TYPE_VIDEO)
Song Zhaoe208d692021-04-19 15:38:52 -07001380 handle_mode_change_v(avsync, v_active, a_active, v_timeout);
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001381 usleep(10000);
Song Zhaoea5a0412021-01-18 16:40:08 -08001382 }
1383 }
1384exit:
1385 log_info("[%d]quit", avsync->session_id);
1386 return NULL;
1387}
1388
Song Zhaod62bb392021-04-23 12:25:49 -07001389int av_sync_set_pcr_clock(void *sync, pts90K pts, uint64_t mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -08001390{
1391 struct av_sync_session *avsync = (struct av_sync_session *)sync;
wei.dubcc2ed22021-05-19 07:16:10 -04001392 struct pcr_info pcr;
1393 enum pcr_monitor_status status;
1394 int ppm;
Song Zhaoea5a0412021-01-18 16:40:08 -08001395 if (!avsync)
1396 return -1;
1397
1398 if (avsync->type != AV_SYNC_TYPE_PCR)
1399 return -2;
1400
wei.dubcc2ed22021-05-19 07:16:10 -04001401 pcr.monoclk = mono_clock / 1000;
1402 pcr.pts = (long long) pts * 1000 / 90;
1403 pcr_monitor_process(avsync->pcr_monitor, &pcr);
1404
1405 status = pcr_monitor_get_status(avsync->pcr_monitor);
1406
1407 if (status >= DEVIATION_READY) {
1408 pcr_monitor_get_deviation(avsync->pcr_monitor, &ppm);
1409 if (avsync->ppm != ppm) {
1410 avsync->ppm = ppm;
1411 log_info("[%d]ppm:%d", avsync->session_id, ppm);
1412 if (msync_session_set_clock_dev(avsync->fd, ppm))
1413 log_error("set clock dev fail");
1414 }
1415 }
1416
Song Zhaod62bb392021-04-23 12:25:49 -07001417 return msync_session_set_pcr(avsync->fd, pts, mono_clock);
Song Zhaoea5a0412021-01-18 16:40:08 -08001418}
1419
Song Zhaod62bb392021-04-23 12:25:49 -07001420int av_sync_get_pcr_clock(void *sync, pts90K *pts, uint64_t * mono_clock)
Song Zhaoea5a0412021-01-18 16:40:08 -08001421{
1422 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1423
1424 if (!avsync)
1425 return -1;
1426
Song Zhaod62bb392021-04-23 12:25:49 -07001427 return msync_session_get_pcr(avsync->fd, pts, mono_clock);
Song Zhaoea5a0412021-01-18 16:40:08 -08001428}
1429
1430int av_sync_set_session_name(void *sync, const char *name)
1431{
1432 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1433
1434 if (!avsync)
1435 return -1;
1436
1437 return msync_session_set_name(avsync->fd, name);
1438}
yongchun.li107a6162021-05-05 02:38:57 -07001439
1440int av_sync_set_audio_switch(void *sync, bool start)
1441{
1442 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1443 bool v_active, a_active, v_timeout;
1444
1445 if (!avsync)
1446 return -1;
1447 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
1448 &v_active, &a_active,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001449 &v_timeout, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -07001450 log_error("[%d] can not get session state",
1451 avsync->session_id);
1452 return -1;
1453 }
1454 if (!v_active || !a_active) {
1455 log_error("[%d] no apply if not AV both active v %d a %d",
1456 avsync->session_id, v_active, a_active);
1457 return -1;
1458 }
1459 if (msync_session_set_audio_switch(avsync->fd, start)) {
1460 log_error("[%d]fail to set audio switch %d", avsync->session_id, start);
1461 return -1;
1462 }
1463 avsync->in_audio_switch = start;
1464 avsync->audio_switch_state = AUDIO_SWITCH_STAT_INIT;
1465 log_info("[%d]update audio switch to %d", avsync->session_id, start);
1466 return 0;
1467}
1468
1469int av_sync_get_audio_switch(void *sync, bool *start)
1470{
1471 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1472
1473 if (!avsync)
1474 return -1;
1475 if (msync_session_get_stat(avsync->fd, &avsync->active_mode,
Song Zhaoe0bf6ad2021-07-09 11:28:42 -07001476 NULL, NULL, NULL, &avsync->in_audio_switch, SRC_A)) {
yongchun.li107a6162021-05-05 02:38:57 -07001477 log_error("[%d] can not audio seamless switch state",
1478 avsync->session_id);
1479 return -1;
1480 }
1481 if (start) *start = avsync->in_audio_switch;
1482 return 0;
Song Zhao7daf3a12021-05-10 22:22:25 -07001483}
Song Zhao8039f562021-05-18 18:11:25 -07001484
1485enum clock_recovery_stat av_sync_get_clock_devication(void *sync, int32_t *ppm)
1486{
1487 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1488
wei.dubcc2ed22021-05-19 07:16:10 -04001489 if (!avsync || !ppm)
1490 return CLK_RECOVERY_ERR;
1491 if (avsync->mode != AV_SYNC_MODE_PCR_MASTER)
Song Zhao8039f562021-05-18 18:11:25 -07001492 return CLK_RECOVERY_NOT_RUNNING;
1493
wei.dubcc2ed22021-05-19 07:16:10 -04001494 if (msync_session_get_clock_dev(avsync->fd, ppm))
1495 return CLK_RECOVERY_ERR;
1496
1497 if (*ppm == 0)
1498 return CLK_RECOVERY_ONGOING;
1499 else
1500 return CLK_RECOVERY_READY;
Song Zhao8039f562021-05-18 18:11:25 -07001501}