blob: 728f3897e5b1dbb22b6c0d3cde7d90afd0bed166 [file] [log] [blame]
Song Zhao6859d412020-06-15 17:16:04 -07001/*
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>
Song Zhao5546ba42020-09-14 21:33:09 -070014#include <sys/time.h>
Song Zhao6859d412020-06-15 17:16:04 -070015
16#include "aml_avsync.h"
17#include "queue.h"
18#include "pattern.h"
19#include "tsync.h"
20#include "aml_avsync_log.h"
21
Song Zhao6859d412020-06-15 17:16:04 -070022enum 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
Song Zhao6859d412020-06-15 17:16:04 -070044 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;
Song Zhao5546ba42020-09-14 21:33:09 -070063
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;
Song Zhao6859d412020-06-15 17:16:04 -070071};
72
73#define MAX_FRAME_NUM 32
74#define DEFAULT_START_THRESHOLD 2
75#define TIME_UNIT90K (90000)
76#define AV_DISCONTINUE_THREDHOLD_MIN (TIME_UNIT90K * 3)
77
Song Zhao5546ba42020-09-14 21:33:09 -070078static uint64_t time_diff (struct timeval *b, struct timeval *a);
Song Zhao6859d412020-06-15 17:16:04 -070079static bool frame_expire(struct av_sync_session* avsync,
80 uint32_t systime,
81 struct vframe * frame,
82 struct vframe * next_frame,
83 int toggle_cnt);
Song Zhao5546ba42020-09-14 21:33:09 -070084static bool frame_expire_pip(struct av_sync_session* avsync,
85 struct vframe * frame);
Song Zhao6859d412020-06-15 17:16:04 -070086static void pattern_detect(struct av_sync_session* avsync,
87 int cur_period,
88 int last_period);
89
Song Zhaobf35d4a2020-06-18 22:36:29 -070090void* av_sync_create(int session_id,
91 enum sync_mode mode,
92 int start_thres,
Song Zhao6859d412020-06-15 17:16:04 -070093 int delay, pts90K vsync_interval)
94{
95 struct av_sync_session *avsync = NULL;
96
97 if (start_thres > 5) {
98 log_error("start_thres too big: %d", start_thres);
99 return NULL;
100 }
101 if (delay != 1 && delay != 2) {
102 log_error("invalid delay: %d\n", delay);
103 return NULL;
104 }
Song Zhaoebb53bb2020-07-10 17:57:34 -0700105 if (vsync_interval < 750 || vsync_interval > 3750) {
Song Zhao6859d412020-06-15 17:16:04 -0700106 log_error("invalid vsync interval: %d", vsync_interval);
107 return NULL;
108 }
Song Zhao5546ba42020-09-14 21:33:09 -0700109 if (session_id != 0 && session_id != 1) {
110 log_error("invalid session: %d", session_id);
111 return NULL;
112 }
Song Zhao6859d412020-06-15 17:16:04 -0700113
114 avsync = (struct av_sync_session *)calloc(1, sizeof(*avsync));
115 if (!avsync) {
116 log_error("OOM");
117 return NULL;
118 }
119 avsync->pattern_detector = create_pattern_detector();
120 if (!avsync->pattern_detector) {
121 log_error("pd create fail");
122 free(avsync);
123 return NULL;
124 }
125 avsync->state = AV_SYNC_STAT_INIT;
126 avsync->first_frame_toggled = false;
127 avsync->paused = false;
128 avsync->phase_set = false;
129 avsync->session_id = session_id;
Song Zhaobf35d4a2020-06-18 22:36:29 -0700130 avsync->mode = mode;
Song Zhao6859d412020-06-15 17:16:04 -0700131 avsync->last_frame = NULL;
132 avsync->tsync_started = false;
Song Zhao5546ba42020-09-14 21:33:09 -0700133 avsync->speed = 1.0f;
134
Song Zhao6859d412020-06-15 17:16:04 -0700135 if (!start_thres)
136 avsync->start_thres = DEFAULT_START_THRESHOLD;
137 else
138 avsync->start_thres = start_thres;
139 avsync->delay = delay;
140 avsync->vsync_interval = vsync_interval;
141
142 avsync->frame_q = create_q(MAX_FRAME_NUM);
143 if (!avsync->frame_q) {
144 log_error("create queue fail");
145 destroy_pattern_detector(avsync->pattern_detector);
146 free(avsync);
147 return NULL;
148 }
149 //TODO: connect kernel session
150
Song Zhao5546ba42020-09-14 21:33:09 -0700151 if (avsync->session_id != 1) {
152 /* just in case sysnode is wrongly set */
153 tsync_send_video_pause(avsync->session_id, false);
154 } else
155 avsync->first_pts = -1;
Song Zhaoebb53bb2020-07-10 17:57:34 -0700156
Song Zhao6859d412020-06-15 17:16:04 -0700157 pthread_mutex_init(&avsync->lock, NULL);
Song Zhao5546ba42020-09-14 21:33:09 -0700158 log_info("mode: %d start_thres: %d delay: %d interval: %d session: %d done\n",
159 mode, start_thres, delay, vsync_interval, session_id);
Song Zhao6859d412020-06-15 17:16:04 -0700160 return avsync;
161}
162
163static int internal_stop(struct av_sync_session *avsync)
164{
165 int ret = 0;
166 struct vframe *frame;
167
168 pthread_mutex_lock(&avsync->lock);
169 if (avsync->state == AV_SYNC_STAT_INIT)
170 goto exit;
171
172 while (!dqueue_item(avsync->frame_q, (void **)&frame)) {
173 frame->free(frame);
174 }
175
176 avsync->state = AV_SYNC_STAT_INIT;
177exit:
178 pthread_mutex_unlock(&avsync->lock);
179 return ret;
180}
181
182/* destroy and detach from kernel session */
183void av_sync_destroy(void *sync)
184{
185 struct av_sync_session *avsync = (struct av_sync_session *)sync;
186
187 if (!avsync)
188 return;
189
190 log_info("begin");
191 if (avsync->state != AV_SYNC_STAT_INIT)
192 internal_stop(avsync);
193
194 /* all frames are freed */
Song Zhao5546ba42020-09-14 21:33:09 -0700195 if (avsync->session_id != 1)
196 tsync_set_pts_inc_mode(avsync->session_id, false);
197
Song Zhao6859d412020-06-15 17:16:04 -0700198 pthread_mutex_destroy(&avsync->lock);
199 destroy_q(avsync->frame_q);
200 destroy_pattern_detector(avsync->pattern_detector);
201 free(avsync);
202 log_info("done");
203}
204
205int av_sync_pause(void *sync, bool pause)
206{
207 struct av_sync_session *avsync = (struct av_sync_session *)sync;
208
209 if (!avsync)
210 return -1;
211
Song Zhao5546ba42020-09-14 21:33:09 -0700212 if (avsync->session_id == 1) {
213 if (!avsync->paused && pause) {
214 gettimeofday(&avsync->pause_start, NULL);
215 avsync->paused = true;
216 }
217 if (avsync->paused && !pause) {
218 struct timeval now;
219
220 gettimeofday(&now, NULL);
221 avsync->pause_duration += time_diff(&now, &avsync->pause_start);
222 avsync->paused = false;
223 }
224 return 0;
225 }
226
Song Zhaode890752020-07-21 13:36:49 -0700227 if (avsync->mode == AV_SYNC_MODE_VMASTER) {
Song Zhaoebb53bb2020-07-10 17:57:34 -0700228 tsync_send_video_pause(avsync->session_id, pause);
Song Zhaode890752020-07-21 13:36:49 -0700229 avsync->paused = pause;
230 log_info("paused:%d\n", pause);
231 } else {
Song Zhao11b851d2020-07-29 16:56:03 -0700232 log_info("ignore paused:%d in mode %d",
233 avsync->paused, avsync->mode);
Song Zhaode890752020-07-21 13:36:49 -0700234 }
Song Zhaoebb53bb2020-07-10 17:57:34 -0700235
Song Zhao6859d412020-06-15 17:16:04 -0700236 return 0;
237}
238
239int av_sync_push_frame(void *sync , struct vframe *frame)
240{
241 int ret;
242 struct av_sync_session *avsync = (struct av_sync_session *)sync;
243
244 if (!avsync)
245 return -1;
246
247 frame->hold_period = 0;
248 ret = queue_item(avsync->frame_q, frame);
249 if (avsync->state == AV_SYNC_STAT_INIT &&
250 queue_size(avsync->frame_q) >= avsync->start_thres) {
251 avsync->state = AV_SYNC_STAT_RUNNING;
252 log_info("state: init --> running");
253 }
254
255 if (ret)
256 log_error("%s queue fail:%d", ret);
257 return ret;
258
259}
260
261struct vframe *av_sync_pop_frame(void *sync)
262{
263 struct vframe *frame = NULL;
264 struct av_sync_session *avsync = (struct av_sync_session *)sync;
265 int toggle_cnt = 0;
Song Zhaobf35d4a2020-06-18 22:36:29 -0700266 uint32_t systime;
Song Zhao6859d412020-06-15 17:16:04 -0700267
268 pthread_mutex_lock(&avsync->lock);
Song Zhaode890752020-07-21 13:36:49 -0700269 if (avsync->state == AV_SYNC_STAT_INIT) {
270 log_trace("in state INIT");
Song Zhao6859d412020-06-15 17:16:04 -0700271 goto exit;
Song Zhaode890752020-07-21 13:36:49 -0700272 }
Song Zhao6859d412020-06-15 17:16:04 -0700273
Song Zhao5546ba42020-09-14 21:33:09 -0700274 if (avsync->session_id == 1) {
275 if (peek_item(avsync->frame_q, (void **)&frame, 0) || !frame) {
276 log_info("empty q");
277 goto exit;
278 }
279
280 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
281 if (frame_expire_pip(avsync, frame)) {
282 toggle_cnt++;
283
284 dqueue_item(avsync->frame_q, (void **)&frame);
285 if (avsync->last_frame) {
286 /* free frame that are not for display */
287 if (toggle_cnt > 1)
288 avsync->last_frame->free(avsync->last_frame);
289 } else {
290 avsync->first_frame_toggled = true;
291 log_info("first frame %u", frame->pts);
292 }
293 avsync->last_frame = frame;
294 } else
295 break;
296 }
297 goto exit;
298 }
299
Song Zhao6859d412020-06-15 17:16:04 -0700300 if (!avsync->tsync_started) {
301 if (peek_item(avsync->frame_q, (void **)&frame, 0) || !frame) {
302 log_info("empty q");
303 goto exit;
304 }
305
Song Zhaobf35d4a2020-06-18 22:36:29 -0700306 if (tsync_enable(avsync->session_id, true))
307 log_error("enable tsync fail");
308 if (avsync->mode == AV_SYNC_MODE_VMASTER) {
309 if (tsync_set_mode(avsync->session_id, AV_SYNC_MODE_VMASTER))
310 log_error("set vmaster mode fail");
311 if (tsync_set_pcr(avsync->session_id, frame->pts))
312 log_error("set pcr fail");
313 log_info("update pcr to: %u", frame->pts);
314 if (tsync_set_pts_inc_mode(avsync->session_id, true))
315 log_error("set inc mode fail");
Song Zhaobf35d4a2020-06-18 22:36:29 -0700316 } else if (avsync->mode == AV_SYNC_MODE_AMASTER) {
Song Zhaoebb53bb2020-07-10 17:57:34 -0700317 if (tsync_set_pts_inc_mode(avsync->session_id, false))
318 log_error("set inc mode fail");
Song Zhaobf35d4a2020-06-18 22:36:29 -0700319 if (tsync_set_mode(avsync->session_id, AV_SYNC_MODE_AMASTER))
320 log_error("set amaster mode fail");
321 } else {
322 //PCR master mode should be set alreay, but it won't hurt to set again.
323 if (tsync_set_mode(avsync->session_id, AV_SYNC_MODE_PCR_MASTER))
324 log_error("set pcrmaster mode fail");
325 }
326
Song Zhao58d3a1c2020-08-04 16:51:30 -0700327 tsync_set_video_peek_mode(avsync->session_id);
328 tsync_disable_video_stop_event(avsync->session_id, true);
Song Zhao0adb3b52020-07-27 16:15:04 -0700329 /* video start ASAP */
330 tsync_set_video_sync_thres(avsync->session_id, false);
Song Zhao6859d412020-06-15 17:16:04 -0700331 /* video start event */
Song Zhaobf35d4a2020-06-18 22:36:29 -0700332 if (tsync_send_video_start(avsync->session_id, frame->pts))
333 log_error("send video start fail");
334 else
335 log_info("video start %u", frame->pts);
Song Zhao6859d412020-06-15 17:16:04 -0700336 avsync->tsync_started = true;
337 }
338
Song Zhaobf35d4a2020-06-18 22:36:29 -0700339 systime = tsync_get_pcr(avsync->session_id);
Song Zhao6859d412020-06-15 17:16:04 -0700340 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
341 struct vframe *next_frame = NULL;
342
343 peek_item(avsync->frame_q, (void **)&next_frame, 1);
344 if (next_frame)
Song Zhaobf35d4a2020-06-18 22:36:29 -0700345 log_debug("cur_f %u next_f %u", frame->pts, next_frame->pts);
Song Zhao6859d412020-06-15 17:16:04 -0700346 if (frame_expire(avsync, systime, frame, next_frame, toggle_cnt)) {
Song Zhaobf35d4a2020-06-18 22:36:29 -0700347 log_debug("cur_f %u expire", frame->pts);
Song Zhao6859d412020-06-15 17:16:04 -0700348 toggle_cnt++;
349
350 pattern_detect(avsync,
351 (avsync->last_frame?avsync->last_frame->hold_period:0),
352 avsync->last_holding_peroid);
353 if (avsync->last_frame)
354 avsync->last_holding_peroid = avsync->last_frame->hold_period;
355
356 dqueue_item(avsync->frame_q, (void **)&frame);
357 if (avsync->last_frame) {
358 /* free frame that are not for display */
359 if (toggle_cnt > 1)
360 avsync->last_frame->free(avsync->last_frame);
361 } else {
362 avsync->first_frame_toggled = true;
Song Zhaobf35d4a2020-06-18 22:36:29 -0700363 log_info("first frame %u", frame->pts);
Song Zhao6859d412020-06-15 17:16:04 -0700364 }
365 avsync->last_frame = frame;
366 } else
367 break;
368 }
369
370exit:
371 pthread_mutex_unlock(&avsync->lock);
372 if (avsync->last_frame)
Song Zhaobf35d4a2020-06-18 22:36:29 -0700373 log_debug("pop %u", avsync->last_frame->pts);
Song Zhao6859d412020-06-15 17:16:04 -0700374 else
375 log_debug("pop (nil)");
376 if (avsync->last_frame)
377 avsync->last_frame->hold_period++;
378 return avsync->last_frame;
379}
380
381void av_sync_update_vsync_interval(void *sync, pts90K vsync_interval)
382{
383 struct av_sync_session *avsync = (struct av_sync_session *)sync;
384
385 pthread_mutex_lock(&avsync->lock);
386 avsync->vsync_interval = vsync_interval;
387 if (avsync->state >= AV_SYNC_STAT_RUNNING) {
388 reset_pattern(avsync->pattern_detector);
389 avsync->phase_set = false;
390 }
391 pthread_mutex_unlock(&avsync->lock);
392}
393
394static inline uint32_t abs_diff(uint32_t a, uint32_t b)
395{
396 return a > b ? a - b : b - a;
397}
398
Song Zhao5546ba42020-09-14 21:33:09 -0700399static uint64_t time_diff (struct timeval *b, struct timeval *a)
400{
401 return (b->tv_sec - a->tv_sec)*1000000 + (b->tv_usec - a->tv_usec);
402}
403
404static bool frame_expire_pip(struct av_sync_session* avsync,
405 struct vframe * frame)
406{
407 struct timeval systime;
408 uint64_t passed;
409 pts90K passed_90k;
410
411 if (avsync->paused)
412 return false;
413
414 gettimeofday(&systime, NULL);
415 if (avsync->first_pts == -1) {
416 avsync->first_pts = frame->pts;
417 avsync->base_sys_time = systime;
418 log_debug("first_pts %u, sys %d/%d", frame->pts,
419 systime.tv_sec, systime.tv_usec);
420 return true;
421 }
422
423 passed = time_diff(&systime, &avsync->base_sys_time);
424 passed -= avsync->pause_duration;
425 passed *= avsync->speed;
426 passed_90k = (pts90K)(passed * 9 / 100);
427
428 if (passed_90k > (frame->pts - avsync->first_pts)) {
429 log_trace("cur_f %u sys: %u/%d stream: %u",
430 frame->pts, systime.tv_sec, systime.tv_usec, passed_90k);
431 return true;
432 }
433
434 return false;
435}
436
Song Zhao6859d412020-06-15 17:16:04 -0700437static bool frame_expire(struct av_sync_session* avsync,
438 uint32_t systime,
439 struct vframe * frame,
440 struct vframe * next_frame,
441 int toggle_cnt)
442{
443 uint32_t fpts = frame->pts;
444 bool expire = false;
445 uint32_t pts_correction = avsync->delay * avsync->vsync_interval;
446
447 if (!fpts) {
448 if (avsync->last_frame) {
449 /* try to accumulate duration as PTS */
450 fpts = avsync->vpts + avsync->last_frame->duration;
451 } else {
452 fpts = avsync->vpts;
453 }
454 }
455 systime += pts_correction;
456
457 /* phase adjustment */
458 if (avsync->phase_set)
459 systime += avsync->phase;
460
Song Zhaobf35d4a2020-06-18 22:36:29 -0700461 log_trace("systime:%u phase:%u correct:%u", systime,
Song Zhao6859d412020-06-15 17:16:04 -0700462 avsync->phase_set?avsync->phase:0, pts_correction);
463 if (abs_diff(systime, fpts) > AV_DISCONTINUE_THREDHOLD_MIN &&
464 avsync->first_frame_toggled) {
465 /* ignore discontinity under pause */
466 if (avsync->paused && avsync->mode != AV_SYNC_MODE_PCR_MASTER)
467 return false;
468
469 log_warn("sync lost systime:%x fpts:%x", systime, fpts);
470 avsync->state = AV_SYNC_STAT_SYNC_LOST;
471 avsync->phase_set = false;
Song Zhaobf35d4a2020-06-18 22:36:29 -0700472 if ((int)(systime - fpts) > 0) {
Song Zhaod3b2b852020-08-10 23:46:43 -0700473 if (frame->pts && avsync->mode == AV_SYNC_MODE_VMASTER)
Song Zhao6859d412020-06-15 17:16:04 -0700474 tsync_send_video_disc(avsync->session_id, frame->pts);
Song Zhaod3b2b852020-08-10 23:46:43 -0700475 /*catch up PCR */
476 return true;
Song Zhao6859d412020-06-15 17:16:04 -0700477 } else if (avsync->mode == AV_SYNC_MODE_PCR_MASTER) {
478 if (frame->pts)
479 tsync_send_video_disc(avsync->session_id, frame->pts);
480 else {
481 tsync_send_video_disc(avsync->session_id, fpts);
482 return true;
483 }
484 }
Song Zhao6859d412020-06-15 17:16:04 -0700485 }
486
Song Zhaoebb53bb2020-07-10 17:57:34 -0700487 expire = (int)(systime - fpts) >= 0;
Song Zhao6859d412020-06-15 17:16:04 -0700488
489 /* scatter the frame in different vsync whenever possible */
490 if (expire && next_frame && next_frame->pts && toggle_cnt) {
491 /* multi frame expired in current vsync but no frame in next vsync */
492 if (systime + avsync->vsync_interval < next_frame->pts) {
493 expire = false;
494 frame->hold_period++;
495 log_debug("unset expire systime:%d inter:%d next_pts:%d toggle_cnt:%d",
496 systime, avsync->vsync_interval, next_frame->pts, toggle_cnt);
497 }
Song Zhaoebb53bb2020-07-10 17:57:34 -0700498 } else if (!expire && next_frame && next_frame->pts && !toggle_cnt
499 && avsync->first_frame_toggled) {
Song Zhao6859d412020-06-15 17:16:04 -0700500 /* next vsync will have at least 2 frame expired */
501 if (systime + avsync->vsync_interval > next_frame->pts) {
502 expire = true;
503 log_debug("set expire systime:%d inter:%d next_pts:%d",
504 systime, avsync->vsync_interval, next_frame->pts);
505 }
506 }
507
508 correct_pattern(avsync->pattern_detector, frame, next_frame,
509 (avsync->last_frame?avsync->last_frame->hold_period:0),
510 avsync->last_holding_peroid, systime,
511 avsync->vsync_interval, &expire);
512
513 if (expire) {
514 avsync->vpts = fpts;
515 /* phase adjustment */
516 if (!avsync->phase_set) {
Song Zhaobf35d4a2020-06-18 22:36:29 -0700517 uint32_t phase_thres = avsync->vsync_interval / 4;
Song Zhao6859d412020-06-15 17:16:04 -0700518 //systime = tsync_get_pcr(avsync->session_id);
Song Zhaobf35d4a2020-06-18 22:36:29 -0700519 if ( systime > fpts && (systime - fpts) < phase_thres) {
520 /* too aligned to current VSYNC, separate them to 1/4 VSYNC */
521 avsync->phase += phase_thres - (systime - fpts);
522 avsync->phase_set = true;
523 log_info("adjust phase to %d", avsync->phase);
524 }
525 if (!avsync->phase_set && systime > fpts &&
526 systime < (fpts + avsync->vsync_interval) &&
527 (systime - fpts) > avsync->vsync_interval - phase_thres) {
528 /* too aligned to previous VSYNC, separate them to 1/4 VSYNC */
529 avsync->phase += phase_thres + fpts + avsync->vsync_interval - systime;
Song Zhao6859d412020-06-15 17:16:04 -0700530 avsync->phase_set = true;
531 log_info("adjust phase to %d", avsync->phase);
532 }
533 }
Song Zhaoebb53bb2020-07-10 17:57:34 -0700534
535 if (avsync->state != AV_SYNC_STAT_SYNC_SETUP)
536 log_info("sync setup");
537 avsync->state = AV_SYNC_STAT_SYNC_SETUP;
Song Zhao6859d412020-06-15 17:16:04 -0700538 }
539
540 return expire;
541}
542
543static void pattern_detect(struct av_sync_session* avsync, int cur_period, int last_period)
544{
545 log_trace("cur_period: %d last_period: %d", cur_period, last_period);
546 detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P32, cur_period, last_period);
547 detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P22, cur_period, last_period);
548 detect_pattern(avsync->pattern_detector, AV_SYNC_FRAME_P41, cur_period, last_period);
Song Zhao6859d412020-06-15 17:16:04 -0700549}
Song Zhaocdf13b62020-08-14 17:46:41 -0700550
551int av_sync_set_speed(void *sync, float speed)
552{
553 struct av_sync_session *avsync = (struct av_sync_session *)sync;
554
555 if (speed < 0.001f || speed > 100) {
556 log_error("wrong speed %f [0.0001, 100]", speed);
557 return -1;
558 }
Song Zhao5546ba42020-09-14 21:33:09 -0700559
560 avsync->speed = speed;
561 if (avsync->session_id == 1)
562 return 0;
563
Song Zhaocdf13b62020-08-14 17:46:41 -0700564 if (avsync->mode != AV_SYNC_MODE_VMASTER) {
565 log_info("ignore set speed in mode %d", avsync->mode);
566 return 0;
567 }
568
569 return tsync_set_speed(avsync->session_id, speed);
570}
Song Zhao7f29c762020-08-21 16:16:29 -0700571
572int av_sync_change_mode(void *sync, enum sync_mode mode)
573{
574 struct av_sync_session *avsync = (struct av_sync_session *)sync;
575
576 if (!avsync)
577 return -1;
Song Zhao5546ba42020-09-14 21:33:09 -0700578
579 if (avsync->session_id == 1)
580 return 0;
581
Song Zhao7f29c762020-08-21 16:16:29 -0700582 if (avsync->mode != AV_SYNC_MODE_VMASTER || mode != AV_SYNC_MODE_AMASTER) {
583 log_error("only support V to A mode switch");
584 return -1;
585 }
586
587 if (tsync_set_pts_inc_mode(avsync->session_id, false))
588 log_error("set inc mode fail");
589 if (tsync_set_mode(avsync->session_id, AV_SYNC_MODE_AMASTER))
590 log_error("set amaster mode fail");
591 avsync->mode = mode;
592 log_info("update sync mode to %d", mode);
593 return 0;
594}