blob: d4d1ab25b009a8073ffad8e9d38de3eec539592b [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 */
9
10#include <pthread.h>
11#include <stdbool.h>
12#include <stdlib.h>
13#include <stdio.h>
14#include <sys/time.h>
15
16#include "aml_avsync.h"
17#include "queue.h"
18#include "pattern.h"
19#include "tsync.h"
20#include "aml_avsync_log.h"
21
22enum sync_state {
23 AV_SYNC_STAT_INIT = 0,
24 AV_SYNC_STAT_RUNNING = 1,
25 AV_SYNC_STAT_SYNC_SETUP = 2,
26 AV_SYNC_STAT_SYNC_LOST = 3,
27};
28
29struct av_sync_session {
30 /* session id attached */
31 int session_id;
32 /* playback time, will stop increasing during pause */
33 pts90K stream_time;
34 pts90K vpts;
35
36 /* phase adjustment of stream time for rate control */
37 pts90K phase;
38 bool phase_set;
39
40 /* pts of last rendered frame */
41 pts90K last_pts;
42 struct vframe *last_frame;
43
44 bool first_frame_toggled;
45 /* Whether in pause state */
46 bool paused;
47 enum sync_mode mode;
48 enum sync_state state;
49 void *pattern_detector;
50 void *frame_q;
51 /* start threshold */
52 int start_thres;
53
54 /* display property */
55 int delay;
56 pts90K vsync_interval;
57
58 /* state lock */
59 pthread_mutex_t lock;
60 /* pattern */
61 int last_holding_peroid;
62 bool tsync_started;
63
64 float speed;
65
66 /*pip sync, remove after multi instance is supported*/
67 struct timeval base_sys_time;
68 struct timeval pause_start;
69 uint64_t pause_duration;
70 pts90K first_pts;
71
72 /* pause pts */
73 pts90K pause_pts;
74 pause_pts_done pause_pts_cb;
75 void *pause_cb_priv;
Song Zhao5d2b4772021-01-18 16:40:08 -080076
77 /* log control */
78 uint32_t last_systime;
79 uint32_t sync_lost_cnt;
80 struct timeval sync_lost_print_time;
Song Zhaoc03ba122020-12-23 21:54:02 -080081};
82
83#define MAX_FRAME_NUM 32
84#define DEFAULT_START_THRESHOLD 2
85#define TIME_UNIT90K (90000)
86#define AV_DISCONTINUE_THREDHOLD_MIN (TIME_UNIT90K * 3)
Song Zhao5d2b4772021-01-18 16:40:08 -080087#define SYNC_LOST_PRINT_THRESHOLD 10000000 //10 seconds In micro seconds
Song Zhaoc03ba122020-12-23 21:54:02 -080088
89static uint64_t time_diff (struct timeval *b, struct timeval *a);
90static bool frame_expire(struct av_sync_session* avsync,
91 uint32_t systime,
92 struct vframe * frame,
93 struct vframe * next_frame,
94 int toggle_cnt);
95static bool frame_expire_pip(struct av_sync_session* avsync,
96 struct vframe * frame);
97static void pattern_detect(struct av_sync_session* avsync,
98 int cur_period,
99 int last_period);
100
101void* av_sync_create(int session_id,
102 enum sync_mode mode,
103 int start_thres,
104 int delay, pts90K vsync_interval)
105{
106 struct av_sync_session *avsync = NULL;
107
108 if (start_thres > 5) {
109 log_error("start_thres too big: %d", start_thres);
110 return NULL;
111 }
112 if (delay != 1 && delay != 2) {
113 log_error("invalid delay: %d\n", delay);
114 return NULL;
115 }
116 if (vsync_interval < 750 || vsync_interval > 3750) {
117 log_error("invalid vsync interval: %d", vsync_interval);
118 return NULL;
119 }
120 if (session_id != 0 && session_id != 1) {
121 log_error("invalid session: %d", session_id);
122 return NULL;
123 }
124
125 avsync = (struct av_sync_session *)calloc(1, sizeof(*avsync));
126 if (!avsync) {
127 log_error("OOM");
128 return NULL;
129 }
130 avsync->pattern_detector = create_pattern_detector();
131 if (!avsync->pattern_detector) {
132 log_error("pd create fail");
133 free(avsync);
134 return NULL;
135 }
136 avsync->state = AV_SYNC_STAT_INIT;
137 avsync->first_frame_toggled = false;
138 avsync->paused = false;
139 avsync->phase_set = false;
140 avsync->session_id = session_id;
141 avsync->mode = mode;
142 avsync->last_frame = NULL;
143 avsync->tsync_started = false;
144 avsync->speed = 1.0f;
145 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
146
147 if (!start_thres)
148 avsync->start_thres = DEFAULT_START_THRESHOLD;
149 else
150 avsync->start_thres = start_thres;
151 avsync->delay = delay;
152 avsync->vsync_interval = vsync_interval;
153
154 avsync->frame_q = create_q(MAX_FRAME_NUM);
155 if (!avsync->frame_q) {
156 log_error("create queue fail");
157 destroy_pattern_detector(avsync->pattern_detector);
158 free(avsync);
159 return NULL;
160 }
161 //TODO: connect kernel session
162
163 if (avsync->session_id != 1) {
164 /* just in case sysnode is wrongly set */
165 tsync_send_video_pause(avsync->session_id, false);
166 } else
167 avsync->first_pts = -1;
168
169 pthread_mutex_init(&avsync->lock, NULL);
170 log_info("mode: %d start_thres: %d delay: %d interval: %d session: %d done\n",
171 mode, start_thres, delay, vsync_interval, session_id);
172 return avsync;
173}
174
175static int internal_stop(struct av_sync_session *avsync)
176{
177 int ret = 0;
178 struct vframe *frame;
179
180 pthread_mutex_lock(&avsync->lock);
181 if (avsync->state == AV_SYNC_STAT_INIT)
182 goto exit;
183
184 while (!dqueue_item(avsync->frame_q, (void **)&frame)) {
185 frame->free(frame);
186 }
187
188 avsync->state = AV_SYNC_STAT_INIT;
189exit:
190 pthread_mutex_unlock(&avsync->lock);
191 return ret;
192}
193
194/* destroy and detach from kernel session */
195void av_sync_destroy(void *sync)
196{
197 struct av_sync_session *avsync = (struct av_sync_session *)sync;
198
199 if (!avsync)
200 return;
201
202 log_info("begin");
203 if (avsync->state != AV_SYNC_STAT_INIT)
204 internal_stop(avsync);
205
206 /* all frames are freed */
Song Zhaoaf368d52021-02-17 17:53:45 -0800207 if (avsync->session_id != 1) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800208 tsync_set_pts_inc_mode(avsync->session_id, false);
Song Zhaoaf368d52021-02-17 17:53:45 -0800209 tsync_send_video_stop(avsync->session_id);
210 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800211
212 pthread_mutex_destroy(&avsync->lock);
213 destroy_q(avsync->frame_q);
214 destroy_pattern_detector(avsync->pattern_detector);
215 free(avsync);
216 log_info("done");
217}
218
219int av_sync_pause(void *sync, bool pause)
220{
221 struct av_sync_session *avsync = (struct av_sync_session *)sync;
222
223 if (!avsync)
224 return -1;
225
226 if (avsync->session_id == 1) {
227 if (!avsync->paused && pause) {
228 gettimeofday(&avsync->pause_start, NULL);
229 avsync->paused = true;
230 }
231 if (avsync->paused && !pause) {
232 struct timeval now;
233
234 gettimeofday(&now, NULL);
235 avsync->pause_duration += time_diff(&now, &avsync->pause_start);
236 avsync->paused = false;
237 }
238 return 0;
239 }
240
241 if (avsync->mode == AV_SYNC_MODE_VMASTER) {
242 tsync_send_video_pause(avsync->session_id, pause);
243 }
244 avsync->paused = pause;
245 log_info("paused:%d\n", pause);
246
247 return 0;
248}
249
250int av_sync_push_frame(void *sync , struct vframe *frame)
251{
252 int ret;
253 struct vframe *prev;
254 struct av_sync_session *avsync = (struct av_sync_session *)sync;
255
256 if (!avsync)
257 return -1;
258
259 if (!peek_item(avsync->frame_q, (void **)&prev, 0)) {
260 if (prev->pts == frame->pts) {
261 dqueue_item(avsync->frame_q, (void **)&prev);
262 prev->free(prev);
263 log_info ("drop frame with same pts %u", frame->pts);
264 }
265 }
266
267 frame->hold_period = 0;
268 ret = queue_item(avsync->frame_q, frame);
269 if (avsync->state == AV_SYNC_STAT_INIT &&
270 queue_size(avsync->frame_q) >= avsync->start_thres) {
271 avsync->state = AV_SYNC_STAT_RUNNING;
272 log_info("state: init --> running");
273 }
274
275 if (ret)
276 log_error("%s queue fail:%d", ret);
277 return ret;
278
279}
280
281struct vframe *av_sync_pop_frame(void *sync)
282{
283 struct vframe *frame = NULL;
284 struct av_sync_session *avsync = (struct av_sync_session *)sync;
285 int toggle_cnt = 0;
286 uint32_t systime;
Song Zhao468fd652021-01-15 22:13:04 -0800287 bool pause_pts_reached = false;
Song Zhaoc03ba122020-12-23 21:54:02 -0800288
289 pthread_mutex_lock(&avsync->lock);
290 if (avsync->state == AV_SYNC_STAT_INIT) {
291 log_trace("in state INIT");
292 goto exit;
293 }
294
295 if (avsync->session_id == 1) {
296 if (peek_item(avsync->frame_q, (void **)&frame, 0) || !frame) {
297 log_info("empty q");
298 goto exit;
299 }
300
301 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
302 if (frame_expire_pip(avsync, frame)) {
303 toggle_cnt++;
304
305 dqueue_item(avsync->frame_q, (void **)&frame);
306 if (avsync->last_frame) {
307 /* free frame that are not for display */
308 if (toggle_cnt > 1)
309 avsync->last_frame->free(avsync->last_frame);
310 } else {
311 avsync->first_frame_toggled = true;
312 log_info("first frame %u", frame->pts);
313 }
314 avsync->last_frame = frame;
315 } else
316 break;
317 }
318 goto exit;
319 }
320
321 if (!avsync->tsync_started) {
322 if (peek_item(avsync->frame_q, (void **)&frame, 0) || !frame) {
323 log_info("empty q");
324 goto exit;
325 }
326
327 if (tsync_enable(avsync->session_id, true))
328 log_error("enable tsync fail");
329 if (avsync->mode == AV_SYNC_MODE_VMASTER) {
330 if (tsync_set_mode(avsync->session_id, AV_SYNC_MODE_VMASTER))
331 log_error("set vmaster mode fail");
332 if (tsync_set_pcr(avsync->session_id, frame->pts))
333 log_error("set pcr fail");
334 log_info("update pcr to: %u", frame->pts);
335 if (tsync_set_pts_inc_mode(avsync->session_id, true))
336 log_error("set inc mode fail");
337 } else if (avsync->mode == AV_SYNC_MODE_AMASTER) {
338 if (tsync_set_pts_inc_mode(avsync->session_id, false))
339 log_error("set inc mode fail");
340 if (tsync_set_mode(avsync->session_id, AV_SYNC_MODE_AMASTER))
341 log_error("set amaster mode fail");
342 } else {
343 //PCR master mode should be set alreay, but it won't hurt to set again.
344 if (tsync_set_mode(avsync->session_id, AV_SYNC_MODE_PCR_MASTER))
345 log_error("set pcrmaster mode fail");
346 }
347
348 tsync_set_video_peek_mode(avsync->session_id);
349 tsync_disable_video_stop_event(avsync->session_id, true);
350 /* video start ASAP */
351 tsync_set_video_sync_thres(avsync->session_id, false);
352 /* video start event */
353 if (tsync_send_video_start(avsync->session_id, frame->pts))
354 log_error("send video start fail");
355 else
356 log_info("video start %u", frame->pts);
357 avsync->tsync_started = true;
358 }
359
360 systime = tsync_get_pcr(avsync->session_id);
361 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
362 struct vframe *next_frame = NULL;
363
364 peek_item(avsync->frame_q, (void **)&next_frame, 1);
365 if (next_frame)
366 log_debug("cur_f %u next_f %u", frame->pts, next_frame->pts);
367 if (frame_expire(avsync, systime, frame, next_frame, toggle_cnt)) {
368 log_debug("cur_f %u expire", frame->pts);
369 toggle_cnt++;
370
371 pattern_detect(avsync,
372 (avsync->last_frame?avsync->last_frame->hold_period:0),
373 avsync->last_holding_peroid);
374 if (avsync->last_frame)
375 avsync->last_holding_peroid = avsync->last_frame->hold_period;
376
377 dqueue_item(avsync->frame_q, (void **)&frame);
378 if (avsync->last_frame) {
379 /* free frame that are not for display */
380 if (toggle_cnt > 1)
381 avsync->last_frame->free(avsync->last_frame);
382 } else {
383 avsync->first_frame_toggled = true;
384 log_info("first frame %u", frame->pts);
385 }
386 avsync->last_frame = frame;
Song Zhao5d2b4772021-01-18 16:40:08 -0800387 avsync->last_pts = frame->pts;
Song Zhaoc03ba122020-12-23 21:54:02 -0800388 } else
389 break;
390 }
391
392 /* pause pts */
393 if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS && avsync->last_frame) {
Song Zhaoc03ba122020-12-23 21:54:02 -0800394 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
Song Zhao468fd652021-01-15 22:13:04 -0800395 pause_pts_reached = true;
Song Zhaoc03ba122020-12-23 21:54:02 -0800396 else
Song Zhao468fd652021-01-15 22:13:04 -0800397 pause_pts_reached = (int)(avsync->last_frame->pts - avsync->pause_pts) >= 0;
398 } else if (avsync->pause_pts != AV_SYNC_INVALID_PAUSE_PTS) {
399 if (!peek_item(avsync->frame_q, (void **)&frame, 0))
400 pause_pts_reached = (int)(frame->pts - avsync->pause_pts) >= 0;
401 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800402
Song Zhao468fd652021-01-15 22:13:04 -0800403 if (pause_pts_reached) {
404 if (avsync->pause_pts_cb)
405 avsync->pause_pts_cb(avsync->pause_pts,
Song Zhaoc03ba122020-12-23 21:54:02 -0800406 avsync->pause_cb_priv);
407
Song Zhao468fd652021-01-15 22:13:04 -0800408 /* stay in paused until av_sync_pause(false) */
409 avsync->paused = true;
410 avsync->pause_pts = AV_SYNC_INVALID_PAUSE_PTS;
411 log_info ("reach pause pts: %u", avsync->last_frame->pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800412 }
413
414exit:
415 pthread_mutex_unlock(&avsync->lock);
416 if (avsync->last_frame) {
417 log_debug("pop %u", avsync->last_frame->pts);
418 tsync_set_vpts(avsync->session_id,avsync->last_frame->pts);
419 } else
420 log_debug("pop (nil)");
421 if (avsync->last_frame)
422 avsync->last_frame->hold_period++;
423 return avsync->last_frame;
424}
425
426void av_sync_update_vsync_interval(void *sync, pts90K vsync_interval)
427{
428 struct av_sync_session *avsync = (struct av_sync_session *)sync;
429
430 pthread_mutex_lock(&avsync->lock);
431 avsync->vsync_interval = vsync_interval;
432 if (avsync->state >= AV_SYNC_STAT_RUNNING) {
433 reset_pattern(avsync->pattern_detector);
434 avsync->phase_set = false;
435 }
436 pthread_mutex_unlock(&avsync->lock);
437}
438
439static inline uint32_t abs_diff(uint32_t a, uint32_t b)
440{
441 return a > b ? a - b : b - a;
442}
443
444static uint64_t time_diff (struct timeval *b, struct timeval *a)
445{
446 return (b->tv_sec - a->tv_sec)*1000000 + (b->tv_usec - a->tv_usec);
447}
448
449static bool frame_expire_pip(struct av_sync_session* avsync,
450 struct vframe * frame)
451{
452 struct timeval systime;
453 uint64_t passed;
454 pts90K passed_90k;
455
456 if (avsync->paused && avsync->pause_pts == AV_SYNC_INVALID_PAUSE_PTS)
457 return false;
458
459 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
460 return true;
461
462 gettimeofday(&systime, NULL);
463 if (avsync->first_pts == -1) {
464 avsync->first_pts = frame->pts;
465 avsync->base_sys_time = systime;
466 log_debug("first_pts %u, sys %d/%d", frame->pts,
467 systime.tv_sec, systime.tv_usec);
468 return true;
469 }
470
471 passed = time_diff(&systime, &avsync->base_sys_time);
472 passed -= avsync->pause_duration;
473 passed *= avsync->speed;
474 passed_90k = (pts90K)(passed * 9 / 100);
475
476 if (passed_90k > (frame->pts - avsync->first_pts)) {
477 log_trace("cur_f %u sys: %u/%d stream: %u",
478 frame->pts, systime.tv_sec, systime.tv_usec, passed_90k);
479 return true;
480 }
481
482 return false;
483}
484
485static bool frame_expire(struct av_sync_session* avsync,
486 uint32_t systime,
487 struct vframe * frame,
488 struct vframe * next_frame,
489 int toggle_cnt)
490{
491 uint32_t fpts = frame->pts;
492 bool expire = false;
493 uint32_t pts_correction = avsync->delay * avsync->vsync_interval;
494
495 if (avsync->paused && avsync->pause_pts == AV_SYNC_INVALID_PAUSE_PTS)
496 return false;
497
498 if (avsync->pause_pts == AV_SYNC_STEP_PAUSE_PTS)
499 return true;
500
501 if (!fpts) {
502 if (avsync->last_frame) {
503 /* try to accumulate duration as PTS */
504 fpts = avsync->vpts + avsync->last_frame->duration;
505 } else {
506 fpts = avsync->vpts;
507 }
508 }
509 systime += pts_correction;
510
511 /* phase adjustment */
512 if (avsync->phase_set)
513 systime += avsync->phase;
514
515 log_trace("systime:%u phase:%u correct:%u", systime,
516 avsync->phase_set?avsync->phase:0, pts_correction);
517 if (abs_diff(systime, fpts) > AV_DISCONTINUE_THREDHOLD_MIN &&
518 avsync->first_frame_toggled) {
519 /* ignore discontinity under pause */
520 if (avsync->paused && avsync->mode != AV_SYNC_MODE_PCR_MASTER)
521 return false;
522
Song Zhao5d2b4772021-01-18 16:40:08 -0800523 if (avsync->last_systime != systime || avsync->last_pts != fpts) {
524 struct timeval now;
525
526 gettimeofday(&now, NULL);
527 avsync->last_systime = systime;
528 avsync->last_pts = fpts;
529 if (time_diff(&now, &avsync->sync_lost_print_time) >=
530 SYNC_LOST_PRINT_THRESHOLD) {
531 log_warn("sync lost systime:%x fpts:%x lost:%u",
532 systime, fpts, avsync->sync_lost_cnt);
533 avsync->sync_lost_cnt = 0;
534 } else
535 avsync->sync_lost_cnt++;
536 }
Song Zhaoc03ba122020-12-23 21:54:02 -0800537 avsync->state = AV_SYNC_STAT_SYNC_LOST;
538 avsync->phase_set = false;
539 if ((int)(systime - fpts) > 0) {
540 if (frame->pts && avsync->mode == AV_SYNC_MODE_VMASTER)
541 tsync_send_video_disc(avsync->session_id, frame->pts);
542 /*catch up PCR */
543 return true;
544 } else if (avsync->mode == AV_SYNC_MODE_PCR_MASTER) {
545 if (frame->pts)
546 tsync_send_video_disc(avsync->session_id, frame->pts);
547 else {
548 tsync_send_video_disc(avsync->session_id, fpts);
549 return true;
550 }
551 }
552 }
553
554 expire = (int)(systime - fpts) >= 0;
555
556 /* scatter the frame in different vsync whenever possible */
557 if (expire && next_frame && next_frame->pts && toggle_cnt) {
558 /* multi frame expired in current vsync but no frame in next vsync */
559 if (systime + avsync->vsync_interval < next_frame->pts) {
560 expire = false;
561 frame->hold_period++;
562 log_debug("unset expire systime:%d inter:%d next_pts:%d toggle_cnt:%d",
563 systime, avsync->vsync_interval, next_frame->pts, toggle_cnt);
564 }
565 } else if (!expire && next_frame && next_frame->pts && !toggle_cnt
566 && avsync->first_frame_toggled) {
567 /* next vsync will have at least 2 frame expired */
568 if (systime + avsync->vsync_interval > next_frame->pts) {
569 expire = true;
570 log_debug("set expire systime:%d inter:%d next_pts:%d",
571 systime, avsync->vsync_interval, next_frame->pts);
572 }
573 }
574
575 correct_pattern(avsync->pattern_detector, frame, next_frame,
576 (avsync->last_frame?avsync->last_frame->hold_period:0),
577 avsync->last_holding_peroid, systime,
578 avsync->vsync_interval, &expire);
579
580 if (expire) {
581 avsync->vpts = fpts;
582 /* phase adjustment */
583 if (!avsync->phase_set) {
584 uint32_t phase_thres = avsync->vsync_interval / 4;
585 //systime = tsync_get_pcr(avsync->session_id);
586 if ( systime > fpts && (systime - fpts) < phase_thres) {
587 /* too aligned to current VSYNC, separate them to 1/4 VSYNC */
588 avsync->phase += phase_thres - (systime - fpts);
589 avsync->phase_set = true;
590 log_info("adjust phase to %d", avsync->phase);
591 }
592 if (!avsync->phase_set && systime > fpts &&
593 systime < (fpts + avsync->vsync_interval) &&
594 (systime - fpts) > avsync->vsync_interval - phase_thres) {
595 /* too aligned to previous VSYNC, separate them to 1/4 VSYNC */
596 avsync->phase += phase_thres + fpts + avsync->vsync_interval - systime;
597 avsync->phase_set = true;
598 log_info("adjust phase to %d", avsync->phase);
599 }
600 }
601
602 if (avsync->state != AV_SYNC_STAT_SYNC_SETUP)
603 log_info("sync setup");
604 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhao5d2b4772021-01-18 16:40:08 -0800605 avsync->sync_lost_cnt = 0;
Song Zhaoc03ba122020-12-23 21:54:02 -0800606 }
607 return expire;
608}
609
610static void pattern_detect(struct av_sync_session* avsync, int cur_period, int last_period)
611{
612 log_trace("cur_period: %d last_period: %d", cur_period, last_period);
613 detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P32, cur_period, last_period);
614 detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P22, cur_period, last_period);
615 detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P41, cur_period, last_period);
616}
617
618int av_sync_set_speed(void *sync, float speed)
619{
620 struct av_sync_session *avsync = (struct av_sync_session *)sync;
621
622 if (speed < 0.001f || speed > 100) {
623 log_error("wrong speed %f [0.0001, 100]", speed);
624 return -1;
625 }
626
627 avsync->speed = speed;
628 if (avsync->session_id == 1)
629 return 0;
630
631 if (avsync->mode != AV_SYNC_MODE_VMASTER) {
632 log_info("ignore set speed in mode %d", avsync->mode);
633 return 0;
634 }
635
636 return tsync_set_speed(avsync->session_id, speed);
637}
638
639int av_sync_change_mode(void *sync, enum sync_mode mode)
640{
641 struct av_sync_session *avsync = (struct av_sync_session *)sync;
642
643 if (!avsync)
644 return -1;
645
646 if (avsync->session_id == 1)
647 return 0;
648
649 if (avsync->mode != AV_SYNC_MODE_VMASTER || mode != AV_SYNC_MODE_AMASTER) {
650 log_error("only support V to A mode switch");
651 return -1;
652 }
653
654 if (tsync_set_pts_inc_mode(avsync->session_id, false))
655 log_error("set inc mode fail");
656 if (tsync_set_mode(avsync->session_id, AV_SYNC_MODE_AMASTER))
657 log_error("set amaster mode fail");
658 avsync->mode = mode;
659 log_info("update sync mode to %d", mode);
660 return 0;
661}
662
663int av_sync_set_pause_pts(void *sync, pts90K pts)
664{
665 struct av_sync_session *avsync = (struct av_sync_session *)sync;
666
667 if (!avsync)
668 return -1;
669
670 avsync->pause_pts = pts;
Song Zhao468fd652021-01-15 22:13:04 -0800671 log_info("set pause pts: %u", pts);
Song Zhaoc03ba122020-12-23 21:54:02 -0800672 return 0;
673}
674
675int av_sync_set_pause_pts_cb(void *sync, pause_pts_done cb, void *priv)
676{
677 struct av_sync_session *avsync = (struct av_sync_session *)sync;
678
679 if (!avsync)
680 return -1;
681
682 avsync->pause_pts_cb = cb;
683 avsync->pause_cb_priv = priv;
684 return 0;
685}