blob: 9cd0c0bc222d85d60af0f774958219b2de09c65a [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 }
Song Zhao1037ec22020-09-26 00:48:43 -0700230 avsync->paused = pause;
231 log_info("paused:%d\n", pause);
Song Zhaoebb53bb2020-07-10 17:57:34 -0700232
Song Zhao6859d412020-06-15 17:16:04 -0700233 return 0;
234}
235
236int av_sync_push_frame(void *sync , struct vframe *frame)
237{
238 int ret;
239 struct av_sync_session *avsync = (struct av_sync_session *)sync;
240
241 if (!avsync)
242 return -1;
243
244 frame->hold_period = 0;
245 ret = queue_item(avsync->frame_q, frame);
246 if (avsync->state == AV_SYNC_STAT_INIT &&
247 queue_size(avsync->frame_q) >= avsync->start_thres) {
248 avsync->state = AV_SYNC_STAT_RUNNING;
249 log_info("state: init --> running");
250 }
251
252 if (ret)
253 log_error("%s queue fail:%d", ret);
254 return ret;
255
256}
257
258struct vframe *av_sync_pop_frame(void *sync)
259{
260 struct vframe *frame = NULL;
261 struct av_sync_session *avsync = (struct av_sync_session *)sync;
262 int toggle_cnt = 0;
Song Zhaobf35d4a2020-06-18 22:36:29 -0700263 uint32_t systime;
Song Zhao6859d412020-06-15 17:16:04 -0700264
265 pthread_mutex_lock(&avsync->lock);
Song Zhaode890752020-07-21 13:36:49 -0700266 if (avsync->state == AV_SYNC_STAT_INIT) {
267 log_trace("in state INIT");
Song Zhao6859d412020-06-15 17:16:04 -0700268 goto exit;
Song Zhaode890752020-07-21 13:36:49 -0700269 }
Song Zhao6859d412020-06-15 17:16:04 -0700270
Song Zhao5546ba42020-09-14 21:33:09 -0700271 if (avsync->session_id == 1) {
272 if (peek_item(avsync->frame_q, (void **)&frame, 0) || !frame) {
273 log_info("empty q");
274 goto exit;
275 }
276
277 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
278 if (frame_expire_pip(avsync, frame)) {
279 toggle_cnt++;
280
281 dqueue_item(avsync->frame_q, (void **)&frame);
282 if (avsync->last_frame) {
283 /* free frame that are not for display */
284 if (toggle_cnt > 1)
285 avsync->last_frame->free(avsync->last_frame);
286 } else {
287 avsync->first_frame_toggled = true;
288 log_info("first frame %u", frame->pts);
289 }
290 avsync->last_frame = frame;
291 } else
292 break;
293 }
294 goto exit;
295 }
296
Song Zhao6859d412020-06-15 17:16:04 -0700297 if (!avsync->tsync_started) {
298 if (peek_item(avsync->frame_q, (void **)&frame, 0) || !frame) {
299 log_info("empty q");
300 goto exit;
301 }
302
Song Zhaobf35d4a2020-06-18 22:36:29 -0700303 if (tsync_enable(avsync->session_id, true))
304 log_error("enable tsync fail");
305 if (avsync->mode == AV_SYNC_MODE_VMASTER) {
306 if (tsync_set_mode(avsync->session_id, AV_SYNC_MODE_VMASTER))
307 log_error("set vmaster mode fail");
308 if (tsync_set_pcr(avsync->session_id, frame->pts))
309 log_error("set pcr fail");
310 log_info("update pcr to: %u", frame->pts);
311 if (tsync_set_pts_inc_mode(avsync->session_id, true))
312 log_error("set inc mode fail");
Song Zhaobf35d4a2020-06-18 22:36:29 -0700313 } else if (avsync->mode == AV_SYNC_MODE_AMASTER) {
Song Zhaoebb53bb2020-07-10 17:57:34 -0700314 if (tsync_set_pts_inc_mode(avsync->session_id, false))
315 log_error("set inc mode fail");
Song Zhaobf35d4a2020-06-18 22:36:29 -0700316 if (tsync_set_mode(avsync->session_id, AV_SYNC_MODE_AMASTER))
317 log_error("set amaster mode fail");
318 } else {
319 //PCR master mode should be set alreay, but it won't hurt to set again.
320 if (tsync_set_mode(avsync->session_id, AV_SYNC_MODE_PCR_MASTER))
321 log_error("set pcrmaster mode fail");
322 }
323
Song Zhao58d3a1c2020-08-04 16:51:30 -0700324 tsync_set_video_peek_mode(avsync->session_id);
325 tsync_disable_video_stop_event(avsync->session_id, true);
Song Zhao0adb3b52020-07-27 16:15:04 -0700326 /* video start ASAP */
327 tsync_set_video_sync_thres(avsync->session_id, false);
Song Zhao6859d412020-06-15 17:16:04 -0700328 /* video start event */
Song Zhaobf35d4a2020-06-18 22:36:29 -0700329 if (tsync_send_video_start(avsync->session_id, frame->pts))
330 log_error("send video start fail");
331 else
332 log_info("video start %u", frame->pts);
Song Zhao6859d412020-06-15 17:16:04 -0700333 avsync->tsync_started = true;
334 }
335
Song Zhaobf35d4a2020-06-18 22:36:29 -0700336 systime = tsync_get_pcr(avsync->session_id);
Song Zhao6859d412020-06-15 17:16:04 -0700337 while (!peek_item(avsync->frame_q, (void **)&frame, 0)) {
338 struct vframe *next_frame = NULL;
339
340 peek_item(avsync->frame_q, (void **)&next_frame, 1);
341 if (next_frame)
Song Zhaobf35d4a2020-06-18 22:36:29 -0700342 log_debug("cur_f %u next_f %u", frame->pts, next_frame->pts);
Song Zhao6859d412020-06-15 17:16:04 -0700343 if (frame_expire(avsync, systime, frame, next_frame, toggle_cnt)) {
Song Zhaobf35d4a2020-06-18 22:36:29 -0700344 log_debug("cur_f %u expire", frame->pts);
Song Zhao6859d412020-06-15 17:16:04 -0700345 toggle_cnt++;
346
347 pattern_detect(avsync,
348 (avsync->last_frame?avsync->last_frame->hold_period:0),
349 avsync->last_holding_peroid);
350 if (avsync->last_frame)
351 avsync->last_holding_peroid = avsync->last_frame->hold_period;
352
353 dqueue_item(avsync->frame_q, (void **)&frame);
354 if (avsync->last_frame) {
355 /* free frame that are not for display */
356 if (toggle_cnt > 1)
357 avsync->last_frame->free(avsync->last_frame);
358 } else {
359 avsync->first_frame_toggled = true;
Song Zhaobf35d4a2020-06-18 22:36:29 -0700360 log_info("first frame %u", frame->pts);
Song Zhao6859d412020-06-15 17:16:04 -0700361 }
362 avsync->last_frame = frame;
363 } else
364 break;
365 }
366
367exit:
368 pthread_mutex_unlock(&avsync->lock);
369 if (avsync->last_frame)
Song Zhaobf35d4a2020-06-18 22:36:29 -0700370 log_debug("pop %u", avsync->last_frame->pts);
Song Zhao6859d412020-06-15 17:16:04 -0700371 else
372 log_debug("pop (nil)");
373 if (avsync->last_frame)
374 avsync->last_frame->hold_period++;
375 return avsync->last_frame;
376}
377
378void av_sync_update_vsync_interval(void *sync, pts90K vsync_interval)
379{
380 struct av_sync_session *avsync = (struct av_sync_session *)sync;
381
382 pthread_mutex_lock(&avsync->lock);
383 avsync->vsync_interval = vsync_interval;
384 if (avsync->state >= AV_SYNC_STAT_RUNNING) {
385 reset_pattern(avsync->pattern_detector);
386 avsync->phase_set = false;
387 }
388 pthread_mutex_unlock(&avsync->lock);
389}
390
391static inline uint32_t abs_diff(uint32_t a, uint32_t b)
392{
393 return a > b ? a - b : b - a;
394}
395
Song Zhao5546ba42020-09-14 21:33:09 -0700396static uint64_t time_diff (struct timeval *b, struct timeval *a)
397{
398 return (b->tv_sec - a->tv_sec)*1000000 + (b->tv_usec - a->tv_usec);
399}
400
401static bool frame_expire_pip(struct av_sync_session* avsync,
402 struct vframe * frame)
403{
404 struct timeval systime;
405 uint64_t passed;
406 pts90K passed_90k;
407
408 if (avsync->paused)
409 return false;
410
411 gettimeofday(&systime, NULL);
412 if (avsync->first_pts == -1) {
413 avsync->first_pts = frame->pts;
414 avsync->base_sys_time = systime;
415 log_debug("first_pts %u, sys %d/%d", frame->pts,
416 systime.tv_sec, systime.tv_usec);
417 return true;
418 }
419
420 passed = time_diff(&systime, &avsync->base_sys_time);
421 passed -= avsync->pause_duration;
422 passed *= avsync->speed;
423 passed_90k = (pts90K)(passed * 9 / 100);
424
425 if (passed_90k > (frame->pts - avsync->first_pts)) {
426 log_trace("cur_f %u sys: %u/%d stream: %u",
427 frame->pts, systime.tv_sec, systime.tv_usec, passed_90k);
428 return true;
429 }
430
431 return false;
432}
433
Song Zhao6859d412020-06-15 17:16:04 -0700434static bool frame_expire(struct av_sync_session* avsync,
435 uint32_t systime,
436 struct vframe * frame,
437 struct vframe * next_frame,
438 int toggle_cnt)
439{
440 uint32_t fpts = frame->pts;
441 bool expire = false;
442 uint32_t pts_correction = avsync->delay * avsync->vsync_interval;
443
Song Zhao353809e2020-10-20 18:03:54 -0700444 if (avsync->paused)
445 return false;
446
Song Zhao6859d412020-06-15 17:16:04 -0700447 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}