blob: 52adfa5f3588c43672eabaf6013360cc81675608 [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>
21#include <unistd.h>
22//#include <linux/amlogic/msync.h>
Song Zhaoc03ba122020-12-23 21:54:02 -080023#include "aml_avsync.h"
24#include "queue.h"
25#include "pattern.h"
Song Zhaoc03ba122020-12-23 21:54:02 -080026#include "aml_avsync_log.h"
Song Zhaoea5a0412021-01-18 16:40:08 -080027#include "msync_util.h"
28#include "msync.h"
29#include <pthread.h>
Song Zhaoc03ba122020-12-23 21:54:02 -080030
31enum sync_state {
32 AV_SYNC_STAT_INIT = 0,
33 AV_SYNC_STAT_RUNNING = 1,
34 AV_SYNC_STAT_SYNC_SETUP = 2,
35 AV_SYNC_STAT_SYNC_LOST = 3,
36};
37
Song Zhaoea5a0412021-01-18 16:40:08 -080038#define SESSION_DEV "avsync_s"
39
Song Zhaoc03ba122020-12-23 21:54:02 -080040struct av_sync_session {
41 /* session id attached */
42 int session_id;
Song Zhaoea5a0412021-01-18 16:40:08 -080043 int fd;
44 bool attached;
45 enum sync_mode mode;
46 /* for audio trickplay */
47 enum sync_mode backup_mode;
48 enum sync_type type;
49 uint32_t start_policy;
Song Zhaoc03ba122020-12-23 21:54:02 -080050
Song Zhaoea5a0412021-01-18 16:40:08 -080051 /* playback time, will stop increasing during pause */
52 pts90K vpts;
53 pts90K apts;
54
55 /* phase adjustment of stream time for rate control (Video ONLY) */
Song Zhaoc03ba122020-12-23 21:54:02 -080056 pts90K phase;
57 bool phase_set;
58
59 /* pts of last rendered frame */
Song Zhaoea5a0412021-01-18 16:40:08 -080060 pts90K last_wall;
Song Zhaoc03ba122020-12-23 21:54:02 -080061 pts90K last_pts;
62 struct vframe *last_frame;
63
64 bool first_frame_toggled;
65 /* Whether in pause state */
66 bool paused;
Song Zhaoea5a0412021-01-18 16:40:08 -080067 enum sync_state state;
Song Zhaoc03ba122020-12-23 21:54:02 -080068 void *pattern_detector;
69 void *frame_q;
Song Zhaoc03ba122020-12-23 21:54:02 -080070
Song Zhaoea5a0412021-01-18 16:40:08 -080071 /* start control */
72 int start_thres;
73 audio_start_cb audio_start;
74 void *audio_start_priv;
75
76 /* render property */
Song Zhaoc03ba122020-12-23 21:54:02 -080077 int delay;
78 pts90K vsync_interval;
79
80 /* state lock */
81 pthread_mutex_t lock;
82 /* pattern */
83 int last_holding_peroid;
Song Zhaoea5a0412021-01-18 16:40:08 -080084 bool session_started;
Song Zhaoc03ba122020-12-23 21:54:02 -080085
86 float speed;
87
Song Zhaoea5a0412021-01-18 16:40:08 -080088#if 0
Song Zhaoc03ba122020-12-23 21:54:02 -080089 /*pip sync, remove after multi instance is supported*/
90 struct timeval base_sys_time;
91 struct timeval pause_start;
92 uint64_t pause_duration;
93 pts90K first_pts;
Song Zhaoea5a0412021-01-18 16:40:08 -080094#endif
Song Zhaoc03ba122020-12-23 21:54:02 -080095
96 /* pause pts */
97 pts90K pause_pts;
98 pause_pts_done pause_pts_cb;
99 void *pause_cb_priv;
Song Zhao5d2b4772021-01-18 16:40:08 -0800100
101 /* log control */
102 uint32_t last_systime;
103 uint32_t sync_lost_cnt;
104 struct timeval sync_lost_print_time;
Song Zhaoea5a0412021-01-18 16:40:08 -0800105
106 pthread_t poll_thread;
107 /* pcr master, IPTV only */
108 bool quit_poll;
109 enum sync_mode active_mode;
Song Zhao35a82df2021-04-15 10:58:49 -0700110
111 /* error detection */
112 uint32_t last_poptime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800113};
114
115#define MAX_FRAME_NUM 32
116#define DEFAULT_START_THRESHOLD 2
117#define TIME_UNIT90K (90000)
Song Zhaoea5a0412021-01-18 16:40:08 -0800118#define AV_DISCONTINUE_THREDHOLD_MIN (TIME_UNIT90K / 3)
119#define A_ADJ_THREDHOLD (TIME_UNIT90K/10)
Song Zhao5d2b4772021-01-18 16:40:08 -0800120#define SYNC_LOST_PRINT_THRESHOLD 10000000 //10 seconds In micro seconds
Song Zhaoc03ba122020-12-23 21:54:02 -0800121
122static uint64_t time_diff (struct timeval *b, struct timeval *a);
123static bool frame_expire(struct av_sync_session* avsync,
124 uint32_t systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800125 uint32_t interval,
Song Zhaoc03ba122020-12-23 21:54:02 -0800126 struct vframe * frame,
127 struct vframe * next_frame,
128 int toggle_cnt);
Song Zhao35a82df2021-04-15 10:58:49 -0700129static bool pattern_detect(struct av_sync_session* avsync,
Song Zhaoc03ba122020-12-23 21:54:02 -0800130 int cur_period,
131 int last_period);
Song Zhaoea5a0412021-01-18 16:40:08 -0800132static void * poll_thread(void * arg);
133static void trigger_audio_start_cb(struct av_sync_session *avsync,
134 avs_ascb_reason reason);
Song Zhaoc03ba122020-12-23 21:54:02 -0800135
Song Zhaoea5a0412021-01-18 16:40:08 -0800136int av_sync_open_session(int *session_id)
137{
138 int fd = msync_create_session();
139 int id, rc;
140
141 if (fd < 0) {
142 log_error("fail");
143 return -1;
144 }
145 rc = ioctl(fd, AMSYNC_IOC_ALLOC_SESSION, &id);
146 if (rc) {
147 log_error("new session errno:%d", errno);
148 return rc;
149 }
150 *session_id = id;
151 return fd;
152}
153
154void av_sync_close_session(int session)
155{
156 msync_destory_session(session);
157}
158
159static void* create_internal(int session_id,
Song Zhaoc03ba122020-12-23 21:54:02 -0800160 enum sync_mode mode,
Song Zhaoea5a0412021-01-18 16:40:08 -0800161 enum sync_type type,
Song Zhaoc03ba122020-12-23 21:54:02 -0800162 int start_thres,
Song Zhaoea5a0412021-01-18 16:40:08 -0800163 bool attach)
Song Zhaoc03ba122020-12-23 21:54:02 -0800164{
165 struct av_sync_session *avsync = NULL;
Song Zhaoea5a0412021-01-18 16:40:08 -0800166 char dev_name[20];
Song Zhaoc03ba122020-12-23 21:54:02 -0800167
168 avsync = (struct av_sync_session *)calloc(1, sizeof(*avsync));
169 if (!avsync) {
170 log_error("OOM");
171 return NULL;
172 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800173
174 if (type == AV_SYNC_TYPE_VIDEO) {
175 avsync->pattern_detector = create_pattern_detector();
176 if (!avsync->pattern_detector) {
177 log_error("pd create fail");
178 goto err;
179 }
180
181 if (!start_thres)
182 avsync->start_thres = DEFAULT_START_THRESHOLD;
183 else {
184 if (start_thres > 5) {
185 log_error("start_thres too big: %d", start_thres);
186 goto err2;
187 }
188 avsync->start_thres = start_thres;
189 }
190 avsync->phase_set = false;
191 avsync->first_frame_toggled = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800192 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800193
194 avsync->type = type;
Song Zhaoc03ba122020-12-23 21:54:02 -0800195 avsync->state = AV_SYNC_STAT_INIT;
Song Zhaoc03ba122020-12-23 21:54:02 -0800196 avsync->paused = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800197 avsync->session_id = session_id;
Song Zhaoea5a0412021-01-18 16:40:08 -0800198 avsync->backup_mode = mode;
Song Zhaoc03ba122020-12-23 21:54:02 -0800199 avsync->last_frame = NULL;
Song Zhaoea5a0412021-01-18 16:40:08 -0800200 avsync->session_started = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800201 avsync->speed = 1.0f;
202 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
Song Zhaoea5a0412021-01-18 16:40:08 -0800203 avsync->vsync_interval = AV_SYNC_INVALID_PAUSE_PTS;
Song Zhaoc03ba122020-12-23 21:54:02 -0800204
205 pthread_mutex_init(&avsync->lock, NULL);
Song Zhaoea5a0412021-01-18 16:40:08 -0800206 log_info("[%d] mode %d type %d start_thres %d",
207 session_id, mode, type, start_thres);
208
209 snprintf(dev_name, sizeof(dev_name), "/dev/%s%d", SESSION_DEV, session_id);
210 avsync->fd = open(dev_name, O_RDONLY | O_CLOEXEC);
211 if (avsync->fd < 0) {
212 log_error("open %s errno %d", dev_name, errno);
213 goto err2;
214 }
215
216 if (!attach) {
217 msync_session_set_mode(avsync->fd, mode);
218 avsync->mode = mode;
219 } else {
220 avsync->attached = true;
221 if (msync_session_get_mode(avsync->fd, &avsync->mode)) {
222 log_error("get mode");
223 goto err2;
224 }
225 avsync->backup_mode = avsync->mode;
226 if (msync_session_get_start_policy(avsync->fd, &avsync->start_policy)) {
227 log_error("get policy");
228 goto err2;
229 }
230 log_info("[%d]retrieve sync mode %d policy %d",
231 session_id, avsync->mode, avsync->start_policy);
232 }
233
Song Zhaoc03ba122020-12-23 21:54:02 -0800234 return avsync;
Song Zhaoea5a0412021-01-18 16:40:08 -0800235err2:
236 destroy_pattern_detector(avsync->pattern_detector);
237err:
238 free(avsync);
239 return NULL;
240}
241
242void* av_sync_create(int session_id,
243 enum sync_mode mode,
244 enum sync_type type,
245 int start_thres)
246{
247 return create_internal(session_id, mode,
248 type, start_thres, false);
249}
250
251void* av_sync_attach(int session_id, enum sync_type type)
252{
253 return create_internal(session_id, AV_SYNC_MODE_MAX,
254 type, 0, true);
255}
256
257int av_sync_video_config(void *sync, struct video_config* config)
258{
259 struct av_sync_session *avsync = (struct av_sync_session *)sync;
260
261 if (!avsync || !config)
262 return -1;
263
264 if (config->delay != 1 && config->delay != 2) {
265 log_error("invalid delay: %d\n", config->delay);
266 return -1;
267 }
268
269 avsync->delay = config->delay;
270
271 log_info("[%d] delay: %d",
272 avsync->session_id, config->delay);
273 return 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800274}
275
276static int internal_stop(struct av_sync_session *avsync)
277{
278 int ret = 0;
279 struct vframe *frame;
280
281 pthread_mutex_lock(&avsync->lock);
Song Zhaoc03ba122020-12-23 21:54:02 -0800282 while (!dqueue_item(avsync->frame_q, (void **)&frame)) {
283 frame->free(frame);
284 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800285 avsync->state = AV_SYNC_STAT_INIT;
Song Zhaoc03ba122020-12-23 21:54:02 -0800286 pthread_mutex_unlock(&avsync->lock);
287 return ret;
288}
289
290/* destroy and detach from kernel session */
291void av_sync_destroy(void *sync)
292{
293 struct av_sync_session *avsync = (struct av_sync_session *)sync;
294
295 if (!avsync)
296 return;
297
Song Zhaoea5a0412021-01-18 16:40:08 -0800298 log_info("[%d]begin", avsync->session_id);
299 if (avsync->state != AV_SYNC_STAT_INIT) {
300 if (avsync->type == AV_SYNC_TYPE_VIDEO)
301 internal_stop(avsync);
Song Zhaoc03ba122020-12-23 21:54:02 -0800302
Song Zhaoea5a0412021-01-18 16:40:08 -0800303 avsync->quit_poll = true;
304 if (avsync->poll_thread) {
305 pthread_join(avsync->poll_thread, NULL);
306 avsync->poll_thread = 0;
307 }
308 trigger_audio_start_cb(avsync, AV_SYNC_ASCB_STOP);
Song Zhaoaf368d52021-02-17 17:53:45 -0800309 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800310
Song Zhaoea5a0412021-01-18 16:40:08 -0800311 if (avsync->session_started) {
312 if (avsync->type == AV_SYNC_TYPE_VIDEO)
313 msync_session_set_video_stop(avsync->fd);
314 else
315 msync_session_set_audio_stop(avsync->fd);
316 }
317 close(avsync->fd);
Song Zhaoc03ba122020-12-23 21:54:02 -0800318 pthread_mutex_destroy(&avsync->lock);
Song Zhaoea5a0412021-01-18 16:40:08 -0800319 if (avsync->type == AV_SYNC_TYPE_VIDEO) {
320 destroy_q(avsync->frame_q);
321 destroy_pattern_detector(avsync->pattern_detector);
322 }
323 log_info("[%d]done", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800324 free(avsync);
Song Zhaoea5a0412021-01-18 16:40:08 -0800325}
326
327int avs_sync_set_start_policy(void *sync, enum sync_start_policy policy)
328{
329 struct av_sync_session *avsync = (struct av_sync_session *)sync;
330
331 if (!avsync || !avsync->fd)
332 return -1;
333
334 log_info("[%d]policy %u --> %u", avsync->start_policy, policy);
335 avsync->start_policy = policy;
336 /* v_peek will be handled by libamlavsync */
337 if (policy != AV_SYNC_START_NONE &&
338 policy != AV_SYNC_START_V_PEEK)
339 return msync_session_set_start_policy(avsync->fd, policy);
340
341 return 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800342}
343
344int av_sync_pause(void *sync, bool pause)
345{
346 struct av_sync_session *avsync = (struct av_sync_session *)sync;
Song Zhaoea5a0412021-01-18 16:40:08 -0800347 int rc;
Song Zhaoc03ba122020-12-23 21:54:02 -0800348
349 if (!avsync)
350 return -1;
351
Song Zhaoea5a0412021-01-18 16:40:08 -0800352 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER)
353 return -1;
Song Zhaoc03ba122020-12-23 21:54:02 -0800354
Song Zhaoea5a0412021-01-18 16:40:08 -0800355 /* ignore */
356 if (avsync->mode == AV_SYNC_MODE_AMASTER && avsync->type == AV_SYNC_TYPE_VIDEO)
Song Zhaoc03ba122020-12-23 21:54:02 -0800357 return 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800358
Song Zhaoea5a0412021-01-18 16:40:08 -0800359 rc = msync_session_set_pause(avsync->fd, pause);
Song Zhaoc03ba122020-12-23 21:54:02 -0800360 avsync->paused = pause;
Song Zhaoea5a0412021-01-18 16:40:08 -0800361 log_info("[%d]paused:%d type:%d rc %d",
362 avsync->session_id, pause, avsync->type, rc);
Song Zhaoc03ba122020-12-23 21:54:02 -0800363
Song Zhaoea5a0412021-01-18 16:40:08 -0800364 return rc;
Song Zhaoc03ba122020-12-23 21:54:02 -0800365}
366
367int av_sync_push_frame(void *sync , struct vframe *frame)
368{
369 int ret;
370 struct vframe *prev;
371 struct av_sync_session *avsync = (struct av_sync_session *)sync;
372
373 if (!avsync)
374 return -1;
375
Song Zhaoea5a0412021-01-18 16:40:08 -0800376 if (!avsync->frame_q) {
377 /* policy should be final now */
378 if (msync_session_get_start_policy(avsync->fd, &avsync->start_policy)) {
379 log_error("[%d]get policy", avsync->session_id);
380 return -1;
381 }
382
383 avsync->frame_q = create_q(MAX_FRAME_NUM);
384 if (!avsync->frame_q) {
385 log_error("[%d]create queue fail", avsync->session_id);
386 return -1;
387 }
388
389 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER ||
390 avsync->mode == AV_SYNC_MODE_IPTV) {
391 int ret;
392
393 ret = pthread_create(&avsync->poll_thread, NULL, poll_thread, avsync);
394 if (ret) {
395 log_error("[%d]create poll thread errno %d", avsync->session_id, errno);
396 destroy_q(avsync->frame_q);
397 return -1;
398 }
399 }
400 }
401
Song Zhaoc03ba122020-12-23 21:54:02 -0800402 if (!peek_item(avsync->frame_q, (void **)&prev, 0)) {
403 if (prev->pts == frame->pts) {
404 dqueue_item(avsync->frame_q, (void **)&prev);
405 prev->free(prev);
Song Zhaoea5a0412021-01-18 16:40:08 -0800406 log_info ("[%d]drop frame with same pts %u", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800407 }
408 }
409
410 frame->hold_period = 0;
411 ret = queue_item(avsync->frame_q, frame);
412 if (avsync->state == AV_SYNC_STAT_INIT &&
413 queue_size(avsync->frame_q) >= avsync->start_thres) {
414 avsync->state = AV_SYNC_STAT_RUNNING;
Song Zhaoea5a0412021-01-18 16:40:08 -0800415 log_info("[%d]state: init --> running", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800416 }
417
418 if (ret)
419 log_error("%s queue fail:%d", ret);
Song Zhaoea5a0412021-01-18 16:40:08 -0800420 log_debug("[%d]push %u", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800421 return ret;
422
423}
424
425struct vframe *av_sync_pop_frame(void *sync)
426{
Song Zhaoea5a0412021-01-18 16:40:08 -0800427 struct vframe *frame = NULL, *enter_last_frame = NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800428 struct av_sync_session *avsync = (struct av_sync_session *)sync;
429 int toggle_cnt = 0;
430 uint32_t systime;
Song Zhao468fd652021-01-15 22:13:04 -0800431 bool pause_pts_reached = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800432 uint32_t interval;
Song Zhaoc03ba122020-12-23 21:54:02 -0800433
434 pthread_mutex_lock(&avsync->lock);
435 if (avsync->state == AV_SYNC_STAT_INIT) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800436 log_trace("[%d]in state INIT", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800437 goto exit;
438 }
439
Song Zhaoea5a0412021-01-18 16:40:08 -0800440 if (!avsync->session_started) {
Song Zhao35a82df2021-04-15 10:58:49 -0700441 uint32_t pts;
442
Song Zhaoc03ba122020-12-23 21:54:02 -0800443 if (peek_item(avsync->frame_q, (void **)&frame, 0) || !frame) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800444 log_info("[%d]empty q", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800445 goto exit;
446 }
Song Zhao35a82df2021-04-15 10:58:49 -0700447 msync_session_get_wall(avsync->fd, &systime, &interval);
448 pts = frame->pts - avsync->delay * interval;
449 msync_session_set_video_start(avsync->fd, pts);
Song Zhaoea5a0412021-01-18 16:40:08 -0800450 avsync->session_started = true;
Song Zhao35a82df2021-04-15 10:58:49 -0700451 log_info("[%d]video start %u", avsync->session_id, pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800452 }
453
Song Zhaoea5a0412021-01-18 16:40:08 -0800454 if (avsync->start_policy == AV_SYNC_START_ALIGN &&
455 !avsync->first_frame_toggled && !msync_clock_started(avsync->fd)) {
456 log_trace("[%d]clock not started", avsync->session_id);
457 return NULL;
Song Zhaoc03ba122020-12-23 21:54:02 -0800458 }
459
Song Zhaoea5a0412021-01-18 16:40:08 -0800460 enter_last_frame = avsync->last_frame;
461 msync_session_get_wall(avsync->fd, &systime, &interval);
462
463 /* handle refresh rate change */
464 if (avsync->vsync_interval == AV_SYNC_INVALID_PAUSE_PTS ||
465 avsync->vsync_interval != interval) {
466 log_info("[%d]vsync interval update %d --> %u",
467 avsync->session_id, avsync->vsync_interval, interval);
468 avsync->vsync_interval = interval;
469 avsync->phase_set = false;
470 reset_pattern(avsync->pattern_detector);
471 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800472 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
473 struct vframe *next_frame = NULL;
474
475 peek_item(avsync->frame_q, (void **)&next_frame, 1);
476 if (next_frame)
Song Zhaoea5a0412021-01-18 16:40:08 -0800477 log_debug("[%d]cur_f %u next_f %u",
478 avsync->session_id, frame->pts, next_frame->pts);
479 if (frame_expire(avsync, systime, interval,
480 frame, next_frame, toggle_cnt)) {
481 log_debug("[%d]cur_f %u expire", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800482 toggle_cnt++;
483
Song Zhao35a82df2021-04-15 10:58:49 -0700484 if (pattern_detect(avsync,
Song Zhaoc03ba122020-12-23 21:54:02 -0800485 (avsync->last_frame?avsync->last_frame->hold_period:0),
Song Zhao35a82df2021-04-15 10:58:49 -0700486 avsync->last_holding_peroid))
487 log_info("[%d] %u break the pattern", avsync->session_id, avsync->last_frame->pts);
488
Song Zhaoc03ba122020-12-23 21:54:02 -0800489 if (avsync->last_frame)
490 avsync->last_holding_peroid = avsync->last_frame->hold_period;
491
492 dqueue_item(avsync->frame_q, (void **)&frame);
493 if (avsync->last_frame) {
494 /* free frame that are not for display */
Song Zhaoea5a0412021-01-18 16:40:08 -0800495 if (toggle_cnt > 1) {
Song Zhao35a82df2021-04-15 10:58:49 -0700496 log_debug("[%d]free %u cur %u system/d %u/%u", avsync->session_id,
497 avsync->last_frame->pts, frame->pts, systime, systime - avsync->last_poptime);
Song Zhaoc03ba122020-12-23 21:54:02 -0800498 avsync->last_frame->free(avsync->last_frame);
Song Zhaoea5a0412021-01-18 16:40:08 -0800499 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800500 } else {
501 avsync->first_frame_toggled = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800502 log_info("[%d]first frame %u", avsync->session_id, frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800503 }
504 avsync->last_frame = frame;
Song Zhao5d2b4772021-01-18 16:40:08 -0800505 avsync->last_pts = frame->pts;
Song Zhaoc03ba122020-12-23 21:54:02 -0800506 } else
507 break;
508 }
509
510 /* pause pts */
511 if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS && avsync->last_frame) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800512 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
Song Zhao468fd652021-01-15 22:13:04 -0800513 pause_pts_reached = true;
Song Zhaoc03ba122020-12-23 21:54:02 -0800514 else
Song Zhao468fd652021-01-15 22:13:04 -0800515 pause_pts_reached = (int)(avsync->last_frame->pts - avsync->pause_pts) >= 0;
516 } else if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS) {
517 if (!peek_item(avsync->frame_q, (void **)&frame, 0))
518 pause_pts_reached = (int)(frame->pts - avsync->pause_pts) >= 0;
519 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800520
Song Zhao468fd652021-01-15 22:13:04 -0800521 if (pause_pts_reached) {
522 if (avsync->pause_pts_cb)
523 avsync->pause_pts_cb(avsync->pause_pts,
Song Zhaoc03ba122020-12-23 21:54:02 -0800524 avsync->pause_cb_priv);
525
Song Zhao468fd652021-01-15 22:13:04 -0800526 /* stay in paused until av_sync_pause(false) */
527 avsync->paused = true;
528 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
Song Zhaoea5a0412021-01-18 16:40:08 -0800529 log_info ("[%d]reach pause pts: %u",
530 avsync->session_id, avsync->last_frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800531 }
532
533exit:
534 pthread_mutex_unlock(&avsync->lock);
535 if (avsync->last_frame) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800536 if (enter_last_frame != avsync->last_frame)
537 log_debug("[%d]pop %u", avsync->session_id, avsync->last_frame->pts);
Song Zhao35a82df2021-04-15 10:58:49 -0700538 log_trace("[%d]pop %u", avsync->session_id, avsync->last_frame->pts);
Song Zhaoea5a0412021-01-18 16:40:08 -0800539 msync_session_update_vpts(avsync->fd, systime,
540 avsync->last_frame->pts, interval * avsync->delay);
Song Zhaoc03ba122020-12-23 21:54:02 -0800541 } else
Song Zhaoea5a0412021-01-18 16:40:08 -0800542 if (enter_last_frame != avsync->last_frame)
543 log_debug("[%d]pop (nil)", avsync->session_id);
544
Song Zhao35a82df2021-04-15 10:58:49 -0700545 avsync->last_poptime = systime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800546 if (avsync->last_frame)
547 avsync->last_frame->hold_period++;
548 return avsync->last_frame;
549}
550
Song Zhaoc03ba122020-12-23 21:54:02 -0800551static inline uint32_t abs_diff(uint32_t a, uint32_t b)
552{
Song Zhaoea5a0412021-01-18 16:40:08 -0800553 return (int)(a - b) > 0 ? a - b : b - a;
Song Zhaoc03ba122020-12-23 21:54:02 -0800554}
555
556static uint64_t time_diff (struct timeval *b, struct timeval *a)
557{
558 return (b->tv_sec - a->tv_sec)*1000000 + (b->tv_usec - a->tv_usec);
559}
560
Song Zhaoc03ba122020-12-23 21:54:02 -0800561static bool frame_expire(struct av_sync_session* avsync,
562 uint32_t systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800563 uint32_t interval,
Song Zhaoc03ba122020-12-23 21:54:02 -0800564 struct vframe * frame,
565 struct vframe * next_frame,
566 int toggle_cnt)
567{
568 uint32_t fpts = frame->pts;
569 bool expire = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800570 uint32_t pts_correction = avsync->delay * interval;
Song Zhaoc03ba122020-12-23 21:54:02 -0800571
572 if (avsync->paused && avsync->pause_pts == AV_SYNC_INVALID_PAUSE_PTS)
573 return false;
574
575 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
576 return true;
577
578 if (!fpts) {
579 if (avsync->last_frame) {
580 /* try to accumulate duration as PTS */
581 fpts = avsync->vpts + avsync->last_frame->duration;
582 } else {
583 fpts = avsync->vpts;
584 }
585 }
586 systime += pts_correction;
587
588 /* phase adjustment */
589 if (avsync->phase_set)
590 systime += avsync->phase;
591
Song Zhao35a82df2021-04-15 10:58:49 -0700592 log_trace("[%d]systime:%u phase:%u correct:%u fpts:%u",
Song Zhaoea5a0412021-01-18 16:40:08 -0800593 avsync->session_id, systime,
Song Zhao35a82df2021-04-15 10:58:49 -0700594 avsync->phase_set?avsync->phase:0, pts_correction, fpts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800595 if (abs_diff(systime, fpts) > AV_DISCONTINUE_THREDHOLD_MIN &&
596 avsync->first_frame_toggled) {
597 /* ignore discontinity under pause */
Song Zhaoea5a0412021-01-18 16:40:08 -0800598 if (avsync->paused)
Song Zhaoc03ba122020-12-23 21:54:02 -0800599 return false;
600
Song Zhao5d2b4772021-01-18 16:40:08 -0800601 if (avsync->last_systime != systime || avsync->last_pts != fpts) {
602 struct timeval now;
603
604 gettimeofday(&now, NULL);
605 avsync->last_systime = systime;
606 avsync->last_pts = fpts;
607 if (time_diff(&now, &avsync->sync_lost_print_time) >=
608 SYNC_LOST_PRINT_THRESHOLD) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800609 log_warn("[%d]sync lost systime:%x fpts:%x lost:%u",
610 avsync->session_id, systime, fpts, avsync->sync_lost_cnt);
Song Zhao5d2b4772021-01-18 16:40:08 -0800611 avsync->sync_lost_cnt = 0;
Song Zhaobc6161d2021-03-08 09:59:33 -0800612 gettimeofday(&avsync->sync_lost_print_time, NULL);
Song Zhao5d2b4772021-01-18 16:40:08 -0800613 } else
614 avsync->sync_lost_cnt++;
615 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800616 avsync->state = AV_SYNC_STAT_SYNC_LOST;
617 avsync->phase_set = false;
Song Zhaoa58c3e92021-03-09 18:52:55 -0800618 reset_pattern(avsync->pattern_detector);
Song Zhaoc03ba122020-12-23 21:54:02 -0800619 if ((int)(systime - fpts) > 0) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800620 if (frame->pts && avsync->mode == AV_SYNC_MODE_VMASTER) {
621 log_info ("[%d]video disc %u --> %u",
622 avsync->session_id, systime, fpts);
623 msync_session_set_video_dis(avsync->fd, frame->pts);
624 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800625 /*catch up PCR */
626 return true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800627 } else if (avsync->mode == AV_SYNC_MODE_PCR_MASTER ||
628 avsync->mode == AV_SYNC_MODE_IPTV) {
629 /* vpts wrapping */
Song Zhaoc03ba122020-12-23 21:54:02 -0800630 if (frame->pts)
Song Zhaoea5a0412021-01-18 16:40:08 -0800631 msync_session_set_video_dis(avsync->fd, frame->pts);
632 else
633 msync_session_set_video_dis(avsync->fd, fpts);
634 return true;
Song Zhaoc03ba122020-12-23 21:54:02 -0800635 }
636 }
637
638 expire = (int)(systime - fpts) >= 0;
639
640 /* scatter the frame in different vsync whenever possible */
641 if (expire && next_frame && next_frame->pts && toggle_cnt) {
642 /* multi frame expired in current vsync but no frame in next vsync */
Song Zhaoea5a0412021-01-18 16:40:08 -0800643 if (systime + interval < next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800644 expire = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800645 log_debug("[%d]unset expire systime:%d inter:%d next_pts:%d toggle_cnt:%d",
646 avsync->session_id, systime, interval, next_frame->pts, toggle_cnt);
Song Zhaoc03ba122020-12-23 21:54:02 -0800647 }
648 } else if (!expire && next_frame && next_frame->pts && !toggle_cnt
649 && avsync->first_frame_toggled) {
650 /* next vsync will have at least 2 frame expired */
Song Zhao35a82df2021-04-15 10:58:49 -0700651 if (systime + interval >= next_frame->pts) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800652 expire = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800653 log_debug("[%d]set expire systime:%d inter:%d next_pts:%d",
654 avsync->session_id, systime, interval, next_frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800655 }
656 }
657
Song Zhaoa58c3e92021-03-09 18:52:55 -0800658 if (avsync->state == AV_SYNC_STAT_SYNC_SETUP)
659 correct_pattern(avsync->pattern_detector, frame, next_frame,
660 (avsync->last_frame?avsync->last_frame->hold_period:0),
661 avsync->last_holding_peroid, systime,
Song Zhaoea5a0412021-01-18 16:40:08 -0800662 interval, &expire);
Song Zhaoc03ba122020-12-23 21:54:02 -0800663
664 if (expire) {
665 avsync->vpts = fpts;
666 /* phase adjustment */
667 if (!avsync->phase_set) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800668 uint32_t phase_thres = interval / 4;
Song Zhaoc03ba122020-12-23 21:54:02 -0800669 if ( systime > fpts && (systime - fpts) < phase_thres) {
670 /* too aligned to current VSYNC, separate them to 1/4 VSYNC */
671 avsync->phase += phase_thres - (systime - fpts);
672 avsync->phase_set = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800673 log_info("[%d]adjust phase to %d", avsync->session_id, avsync->phase);
Song Zhaoc03ba122020-12-23 21:54:02 -0800674 }
675 if (!avsync->phase_set && systime > fpts &&
Song Zhaoea5a0412021-01-18 16:40:08 -0800676 systime < (fpts + interval) &&
677 (systime - fpts) > interval - phase_thres) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800678 /* too aligned to previous VSYNC, separate them to 1/4 VSYNC */
Song Zhaoea5a0412021-01-18 16:40:08 -0800679 avsync->phase += phase_thres + fpts + interval - systime;
Song Zhaoc03ba122020-12-23 21:54:02 -0800680 avsync->phase_set = true;
Song Zhaoea5a0412021-01-18 16:40:08 -0800681 log_info("[%d]adjust phase to %d", avsync->session_id, avsync->phase);
Song Zhaoc03ba122020-12-23 21:54:02 -0800682 }
683 }
684
685 if (avsync->state != AV_SYNC_STAT_SYNC_SETUP)
Song Zhaoea5a0412021-01-18 16:40:08 -0800686 log_info("[%d]sync setup", avsync->session_id);
Song Zhaoc03ba122020-12-23 21:54:02 -0800687 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhao5d2b4772021-01-18 16:40:08 -0800688 avsync->sync_lost_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800689 }
690 return expire;
691}
692
Song Zhao35a82df2021-04-15 10:58:49 -0700693static bool pattern_detect(struct av_sync_session* avsync, int cur_period, int last_period)
Song Zhaoc03ba122020-12-23 21:54:02 -0800694{
Song Zhao35a82df2021-04-15 10:58:49 -0700695 bool ret = false;
Song Zhaoea5a0412021-01-18 16:40:08 -0800696 log_trace("[%d]cur_period: %d last_period: %d",
697 avsync->session_id, cur_period, last_period);
Song Zhao35a82df2021-04-15 10:58:49 -0700698 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P32, cur_period, last_period))
699 ret = true;
700 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P22, cur_period, last_period))
701 ret = true;
702 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P41, cur_period, last_period))
703 ret = true;
704 if (detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P11, cur_period, last_period))
705 ret = true;
706
707 return ret;
Song Zhaoc03ba122020-12-23 21:54:02 -0800708}
709
710int av_sync_set_speed(void *sync, float speed)
711{
712 struct av_sync_session *avsync = (struct av_sync_session *)sync;
713
714 if (speed < 0.001f || speed > 100) {
Song Zhaoea5a0412021-01-18 16:40:08 -0800715 log_error("[%d]wrong speed %f [0.0001, 100]", avsync->session_id, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -0800716 return -1;
717 }
718
Song Zhaoea5a0412021-01-18 16:40:08 -0800719 if (avsync->mode == AV_SYNC_MODE_PCR_MASTER ||
720 avsync->mode == AV_SYNC_MODE_IPTV) {
721 log_info("[%d]ignore set speed in mode %d", avsync->session_id, avsync->mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800722 return 0;
Song Zhaoea5a0412021-01-18 16:40:08 -0800723 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800724
Song Zhaoea5a0412021-01-18 16:40:08 -0800725 avsync->speed = speed;
726
727 if (avsync->type == AV_SYNC_TYPE_AUDIO) {
728 if (speed == 1.0) {
729 avsync->mode = avsync->backup_mode;
730 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
731 } else {
732 avsync->backup_mode = avsync->mode;
733 avsync->mode = AV_SYNC_MODE_FREE_RUN;
734 log_info("[%d]audio to freerun mode", avsync->session_id);
735 }
736 }
737#if 0
Song Zhaoc03ba122020-12-23 21:54:02 -0800738 if (avsync->mode != AV_SYNC_MODE_VMASTER) {
739 log_info("ignore set speed in mode %d", avsync->mode);
740 return 0;
741 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800742#endif
Song Zhaoc03ba122020-12-23 21:54:02 -0800743
Song Zhaoea5a0412021-01-18 16:40:08 -0800744 log_info("session[%d] set rate to %f", avsync->session_id, speed);
745 return msync_session_set_rate(avsync->fd, speed);
Song Zhaoc03ba122020-12-23 21:54:02 -0800746}
747
748int av_sync_change_mode(void *sync, enum sync_mode mode)
749{
750 struct av_sync_session *avsync = (struct av_sync_session *)sync;
751
752 if (!avsync)
753 return -1;
754
Song Zhaoea5a0412021-01-18 16:40:08 -0800755 if (msync_session_set_mode(avsync->fd, mode)) {
756 log_error("[%d]fail to set mode %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800757 return -1;
758 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800759 avsync->mode = mode;
Song Zhaoea5a0412021-01-18 16:40:08 -0800760 log_info("[%d]update sync mode to %d", avsync->session_id, mode);
Song Zhaoc03ba122020-12-23 21:54:02 -0800761 return 0;
762}
763
764int av_sync_set_pause_pts(void *sync, pts90K pts)
765{
766 struct av_sync_session *avsync = (struct av_sync_session *)sync;
767
768 if (!avsync)
769 return -1;
770
771 avsync->pause_pts = pts;
Song Zhaoea5a0412021-01-18 16:40:08 -0800772 log_info("[%d]set pause pts: %u", avsync->session_id, pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800773 return 0;
774}
775
776int av_sync_set_pause_pts_cb(void *sync, pause_pts_done cb, void *priv)
777{
778 struct av_sync_session *avsync = (struct av_sync_session *)sync;
779
780 if (!avsync)
781 return -1;
782
783 avsync->pause_pts_cb = cb;
784 avsync->pause_cb_priv = priv;
785 return 0;
786}
Song Zhaoea5a0412021-01-18 16:40:08 -0800787
788static void trigger_audio_start_cb(struct av_sync_session *avsync,
789 avs_ascb_reason reason)
790{
791 if (avsync) {
792 pthread_mutex_lock(&avsync->lock);
793 if (avsync->audio_start) {
794 avsync->audio_start(avsync->audio_start_priv, reason);
795 avsync->session_started = true;
796 avsync->audio_start = NULL;
797 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
798 }
799 pthread_mutex_unlock(&avsync->lock);
800 }
801}
802
803avs_start_ret av_sync_audio_start(
804 void *sync,
805 pts90K pts,
806 pts90K delay,
807 audio_start_cb cb,
808 void *priv)
809{
810 struct av_sync_session *avsync = (struct av_sync_session *)sync;
811 uint32_t start_mode;
812 avs_start_ret ret = AV_SYNC_ASTART_ERR;
813 bool create_poll_t = false;
814
815 if (!avsync)
816 return ret;
817
818 if (msync_session_set_audio_start(avsync->fd, pts, delay, &start_mode))
819 log_error("[%d]fail to set audio start", avsync->session_id);
820
821 avsync->state = AV_SYNC_STAT_RUNNING;
822 if (start_mode == AVS_START_SYNC) {
823 ret = AV_SYNC_ASTART_SYNC;
824 avsync->session_started = true;
825 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
826 } else if (start_mode == AVS_START_ASYNC)
827 ret = AV_SYNC_ASTART_ASYNC;
828
829 if (avsync->mode == AV_SYNC_MODE_AMASTER) {
830 create_poll_t = true;
831 if (start_mode == AVS_START_ASYNC) {
832 if (!cb) {
833 log_error("[%d]invalid cb", avsync->session_id);
834 return AV_SYNC_ASTART_ERR;
835 }
836 avsync->audio_start = cb;
837 avsync->audio_start_priv = priv;
838 }
839 } else if (avsync->mode == AV_SYNC_MODE_PCR_MASTER || start_mode == AV_SYNC_MODE_IPTV)
840 create_poll_t = true;
841
842 if (create_poll_t) {
843 int ret;
844
845 log_info("[%d]start poll thread", avsync->session_id);
846 avsync->quit_poll = false;
847 ret = pthread_create(&avsync->poll_thread, NULL, poll_thread, avsync);
848 if (ret) {
849 log_error("[%d]create poll thread errno %d", avsync->session_id, errno);
850 return AV_SYNC_ASTART_ERR;
851 }
852 }
853
854 log_info("[%d]return %u", avsync->session_id, ret);
855 return ret;
856}
857
858int av_sync_audio_render(
859 void *sync,
860 pts90K pts,
861 struct audio_policy *policy)
862{
863 int ret = 0;
864 uint32_t systime;
865 struct av_sync_session *avsync = (struct av_sync_session *)sync;
866 avs_audio_action action = AA_SYNC_AA_MAX;
867
868 if (!avsync || !policy)
869 return -1;
870
871 if (avsync->mode == AV_SYNC_MODE_FREE_RUN ||
872 avsync->mode == AV_SYNC_MODE_AMASTER) {
873 action = AV_SYNC_AA_RENDER;
874 goto done;
875 }
876
877 msync_session_get_wall(avsync->fd, &systime, NULL);
878 if (abs_diff(systime, pts) < A_ADJ_THREDHOLD) {
879 action = AV_SYNC_AA_RENDER;
880 goto done;
881 }
882
883 if ((int)(systime - pts) > 0) {
884 action = AV_SYNC_AA_DROP;
885 goto done;
886 }
887
888 if ((int)(systime - pts) < 0) {
889 action = AV_SYNC_AA_INSERT;
890 goto done;
891 }
892
893done:
894 policy->action = action;
895 policy->delta = (int)(systime - pts);
896 if (action == AV_SYNC_AA_RENDER) {
897 avsync->apts = pts;
898 msync_session_update_apts(avsync->fd, systime, pts, 0);
899 } else {
900 log_info("[%d]return %d sys %u pts %u", avsync->session_id, action, systime, pts);
901 }
902
903 return ret;
904}
905
906int av_sync_get_clock(void *sync, pts90K *pts)
907{
908 struct av_sync_session *avsync = (struct av_sync_session *)sync;
909
910 if (!avsync || !pts)
911 return -1;
912 return msync_session_get_wall(avsync->fd, pts, NULL);
913}
914
915static void handle_mode_change_a(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -0700916 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -0800917{
Song Zhaoe208d692021-04-19 15:38:52 -0700918 log_info("[%d]amode %d mode %d v/a/vt %d/%d/%d", avsync->session_id,
919 avsync->active_mode, avsync->mode, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -0800920 if (avsync->active_mode == AV_SYNC_MODE_AMASTER) {
921 float speed;
922 if (avsync->start_policy == AV_SYNC_START_ALIGN &&
Song Zhaoe208d692021-04-19 15:38:52 -0700923 a_active && avsync->audio_start) {
924 if (v_active || v_timeout) {
925 log_info("audio start cb");
926 trigger_audio_start_cb(avsync, AV_SYNC_ASCB_OK);
927 }
Song Zhaoea5a0412021-01-18 16:40:08 -0800928 }
929
930 if (!msync_session_get_rate(avsync->fd, &speed)) {
931 /* speed change is triggered by asink,
932 * attached audio HAL will handle it
933 */
934 if (speed != avsync->speed)
935 log_info("[%d]new rate %f", avsync->session_id, speed);
936 if (speed == 1.0) {
937 avsync->mode = avsync->backup_mode;
938 log_info("[%d]audio back to mode %d", avsync->session_id, avsync->mode);
939 } else {
940 avsync->backup_mode = avsync->mode;
941 avsync->mode = AV_SYNC_MODE_FREE_RUN;
942 log_info("[%d]audio to freerun mode", avsync->session_id);
943 }
944 avsync->speed = speed;
945 }
946 }
947}
948
949static void handle_mode_change_v(struct av_sync_session* avsync,
Song Zhaoe208d692021-04-19 15:38:52 -0700950 bool v_active, bool a_active, bool v_timeout)
Song Zhaoea5a0412021-01-18 16:40:08 -0800951{
952 log_info("[%d]amode mode %d %d v/a %d/%d", avsync->session_id,
953 avsync->active_mode, avsync->mode, v_active, a_active);
954}
955
956static void * poll_thread(void * arg)
957{
958 int ret = 0;
959 struct av_sync_session *avsync = (struct av_sync_session *)arg;
960 const int fd = avsync->fd;
961 struct pollfd pfd = {
962 /* default blocking capture */
963 .events = POLLIN | POLLRDNORM | POLLPRI | POLLOUT | POLLWRNORM,
964 .fd = avsync->fd,
965 };
966
967 prctl (PR_SET_NAME, "avs_poll");
968 log_info("[%d]enter", avsync->session_id);
969 while (!avsync->quit_poll) {
970 for (;;) {
971 ret = poll(&pfd, 1, 10);
972 if (ret > 0)
973 break;
974 if (avsync->quit_poll)
975 goto exit;
976 if (errno == EINTR)
977 continue;
978 }
979
980 /* error handling */
981 if (pfd.revents & POLLERR)
982 log_error("[%d]POLLERR received", avsync->session_id);
983
984 /* mode change */
985 if (pfd.revents & POLLPRI) {
Song Zhaoe208d692021-04-19 15:38:52 -0700986 bool v_active, a_active, v_timeout;
Song Zhaoea5a0412021-01-18 16:40:08 -0800987
988 msync_session_get_stat(fd, &avsync->active_mode,
Song Zhaoe208d692021-04-19 15:38:52 -0700989 &v_active, &a_active, &v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -0800990
991 if (avsync->type == AV_SYNC_TYPE_AUDIO)
Song Zhaoe208d692021-04-19 15:38:52 -0700992 handle_mode_change_a(avsync, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -0800993 else if (avsync->type == AV_SYNC_TYPE_VIDEO)
Song Zhaoe208d692021-04-19 15:38:52 -0700994 handle_mode_change_v(avsync, v_active, a_active, v_timeout);
Song Zhaoea5a0412021-01-18 16:40:08 -0800995 }
996 }
997exit:
998 log_info("[%d]quit", avsync->session_id);
999 return NULL;
1000}
1001
1002int av_sync_set_pcr_clock(void *sync, pts90K pts)
1003{
1004 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1005
1006 if (!avsync)
1007 return -1;
1008
1009 if (avsync->type != AV_SYNC_TYPE_PCR)
1010 return -2;
1011
1012 return msync_session_set_pcr(avsync->fd, pts);
1013}
1014
1015int av_sync_get_pcr_clock(void *sync, pts90K *pts)
1016{
1017 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1018
1019 if (!avsync)
1020 return -1;
1021
1022 if (avsync->type != AV_SYNC_TYPE_PCR)
1023 return -2;
1024
1025 return msync_session_get_pcr(avsync->fd, pts);
1026}
1027
1028int av_sync_set_session_name(void *sync, const char *name)
1029{
1030 struct av_sync_session *avsync = (struct av_sync_session *)sync;
1031
1032 if (!avsync)
1033 return -1;
1034
1035 return msync_session_set_name(avsync->fd, name);
1036}