summaryrefslogtreecommitdiff
path: root/amadec/adec-pts-mgt.c (plain)
blob: fd627f73f871753be704322a8a02d5d09409b931
1/**
2 * \file adec-pts-mgt.c
3 * \brief Functions Of Pts Manage.
4 * \version 1.0.0
5 * \date 2011-03-08
6 */
7/* Copyright (C) 2007-2011, Amlogic Inc.
8 * All right reserved
9 *
10 */
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <fcntl.h>
15#include <errno.h>
16#include <unistd.h>
17
18#include <adec-pts-mgt.h>
19#include <cutils/properties.h>
20#include <sys/time.h>
21#include <amthreadpool.h>
22#include <sys/ioctl.h>
23
24#include "Amsysfsutils.h"
25#include "amconfigutils.h"
26
27#define DROP_PCM_DURATION_THRESHHOLD 4 //unit:s
28#define DROP_PCM_MAX_TIME 1000 // unit :ms
29#define DROP_PCM_PTS_DIFF_THRESHHOLD 90000*10
30#define DROP_PCM_RESET_PCR_THRESHOLD 90000/2
31
32int adec_pts_droppcm(aml_audio_dec_t *audec);
33int vdec_pts_resume(void);
34static int vdec_pts_pause(void);
35int droppcm_use_size(aml_audio_dec_t *audec, int drop_size);
36void droppcm_prop_ctrl(int *audio_ahead, int *pts_ahead_val);
37int droppcm_get_refpts(aml_audio_dec_t *audec, unsigned long *refpts);
38
39extern int match_types(const char *filetypestr, const char *typesetting);
40
41static int64_t gettime(void)
42{
43 struct timeval tv;
44 gettimeofday(&tv, NULL);
45 return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
46}
47
48int sysfs_get_int(char *path, unsigned long *val)
49{
50 char buf[64];
51
52 if (amsysfs_get_sysfs_str(path, buf, sizeof(buf)) == -1) {
53 adec_print("unable to open file %s,err: %s", path, strerror(errno));
54 return -1;
55 }
56 if (sscanf(buf, "0x%lx", val) < 1) {
57 adec_print("unable to get pts from: %s", buf);
58 return -1;
59 }
60
61 return 0;
62}
63/*
64get vpts when refresh apts, do not use sys write servie as it is too slow sometimes.
65*/
66static int mysysfs_get_sysfs_int16(const char *path)
67{
68 int fd;
69 char valstr[64];
70 int val;
71 fd = open(path, O_RDONLY);
72 if (fd >= 0) {
73 memset(valstr, 0, 64);
74 read(fd, valstr, 64 - 1);
75 valstr[strlen(valstr)] = '\0';
76 close(fd);
77 } else {
78 adec_print("unable to open file %s\n", path);
79 return -1;
80 }
81 if (sscanf(valstr, "0x%x", &val) < 1) {
82 adec_print("unable to get pts from: %s", valstr);
83 return -1;
84 }
85 return val;
86}
87
88static int mysysfs_get_sysfs_int(const char *path)
89{
90 int fd;
91 int val = 0;
92 char bcmd[16];
93 fd = open(path, O_RDONLY);
94 if (fd >= 0) {
95 read(fd, bcmd, sizeof(bcmd));
96 val = strtol(bcmd, NULL, 10);
97 close(fd);
98 } else {
99 adec_print("unable to open file %s,err: %s", path, strerror(errno));
100 }
101 return val;
102}
103
104static int set_tsync_enable(int enable)
105{
106 char *path = "/sys/class/tsync/enable";
107 return amsysfs_set_sysfs_int(path, enable);
108}
109/**
110 * \brief calc current pts
111 * \param audec pointer to audec
112 * \return aurrent audio pts
113 */
114unsigned long adec_calc_pts(aml_audio_dec_t *audec)
115{
116 unsigned long pts, delay_pts;
117 audio_out_operations_t *out_ops;
118 dsp_operations_t *dsp_ops;
119
120 out_ops = &audec->aout_ops;
121 dsp_ops = &audec->adsp_ops;
122
123 pts = dsp_ops->get_cur_pts(dsp_ops);
124 if (pts == -1) {
125 adec_print("get get_cur_pts failed\n");
126 return -1;
127 }
128 dsp_ops->kernel_audio_pts = pts;
129
130 if (out_ops == NULL || out_ops->latency == NULL) {
131 adec_print("cur_out is NULL!\n ");
132 return -1;
133 }
134 delay_pts = out_ops->latency(audec) * 90;
135
136 if (!audec->apts_start_flag) {
137 return pts;
138 }
139
140 int diff = abs(delay_pts - pts);
141 // in some case, audio latency got from audiotrack is bigger than pts<hw not enabled>, so when delay_pts-pts < 100ms ,so set apts to 0.
142 //because 100ms pcr-apts diff cause apts reset .
143 if (delay_pts/*+audec->first_apts*/ < pts) {
144 pts -= delay_pts;
145 } else if (diff < 9000) {
146 pts = 0;
147 }
148 return pts;
149}
150
151/**
152 * \brief start pts manager
153 * \param audec pointer to audec
154 * \return 0 on success otherwise -1
155 */
156int adec_pts_start(aml_audio_dec_t *audec)
157{
158 unsigned long pts = 0;
159 char *file;
160 char buf[64];
161 dsp_operations_t *dsp_ops;
162 char value[PROPERTY_VALUE_MAX] = {0};
163 int tsync_mode;
164 unsigned long first_apts = 0;
165
166 adec_print("adec_pts_start");
167 dsp_ops = &audec->adsp_ops;
168 memset(buf, 0, sizeof(buf));
169
170 if (audec->avsync_threshold <= 0) {
171 if (am_getconfig_bool("media.libplayer.wfd")) {
172 audec->avsync_threshold = SYSTIME_CORRECTION_THRESHOLD * 2 / 3;
173 adec_print("use 2/3 default av sync threshold!\n");
174 } else {
175 audec->avsync_threshold = SYSTIME_CORRECTION_THRESHOLD;
176 adec_print("use default av sync threshold!\n");
177 }
178 }
179
180 first_apts = adec_calc_pts(audec);
181 if (sysfs_get_int(TSYNC_FIRSTAPTS, &audec->first_apts) == -1) {
182 adec_print("## [%s::%d] unable to get first_apts! \n", __FUNCTION__, __LINE__);
183 return -1;
184 }
185
186 adec_print("av sync threshold is %d , no_first_apts=%d,first_apts = 0x%x, audec->first_apts = 0x%x \n", audec->avsync_threshold, audec->no_first_apts, first_apts, audec->first_apts);
187
188
189 dsp_ops->last_pts_valid = 0;
190
191 //default enable drop pcm
192 int enable_drop_pcm = 1;
193 if (property_get("sys.amplayer.drop_pcm", value, NULL) > 0) {
194 enable_drop_pcm = atoi(value);
195 }
196 adec_print("[%s:%d] enable_drop_pcm :%d \n", __FUNCTION__, __LINE__, enable_drop_pcm);
197 if (enable_drop_pcm) {
198 char *path = "/sys/class/tsync/enable";
199 char buf[32] = "";
200
201 if (amsysfs_get_sysfs_str(path, buf, 32) >= 0) {
202 if (!strncmp(buf, "1: enabled", 10)) {
203 adec_pts_droppcm(audec);
204 }
205 } else {
206 adec_print("## [%s::%d] unable to get tsync enable status! \n", __FUNCTION__, __LINE__);
207 }
208 }
209
210 // before audio start or pts start
211 if (amsysfs_set_sysfs_str(TSYNC_EVENT, "AUDIO_PRE_START") == -1) {
212 return -1;
213 }
214
215 amthreadpool_thread_usleep(1000);
216
217 if (audec->no_first_apts) {
218 if (amsysfs_get_sysfs_str(TSYNC_APTS, buf, sizeof(buf)) == -1) {
219 adec_print("unable to open file %s,err: %s", TSYNC_APTS, strerror(errno));
220 return -1;
221 }
222
223 if (sscanf(buf, "0x%lx", &pts) < 1) {
224 adec_print("unable to get vpts from: %s", buf);
225 return -1;
226 }
227
228 } else {
229 pts = adec_calc_pts(audec);
230
231 if (pts == -1) {
232
233 adec_print("pts==-1");
234
235 if (amsysfs_get_sysfs_str(TSYNC_APTS, buf, sizeof(buf)) == -1) {
236 adec_print("unable to open file %s,err: %s", TSYNC_APTS, strerror(errno));
237 return -1;
238 }
239
240 if (sscanf(buf, "0x%lx", &pts) < 1) {
241 adec_print("unable to get apts from: %s", buf);
242 return -1;
243 }
244 }
245 }
246
247 return 0;
248}
249
250static void enable_slowsync_repeate()
251{
252 const char * slowsync_path = "/sys/class/tsync/slowsync_enable";
253 const char * slowsync_repeate_path = "/sys/class/video/slowsync_repeat_enable";
254 //amsysfs_set_sysfs_int(slowsync_path, 1);
255 amsysfs_set_sysfs_int(slowsync_repeate_path, 1);
256 adec_print("enable slowsync repeate. \n");
257}
258
259int adec_pts_droppcm(aml_audio_dec_t *audec)
260{
261 unsigned long refpts, apts, oldapts;
262 int ret, drop_size, droppts, dropms;
263 char value[PROPERTY_VALUE_MAX] = {0};
264 int64_t starttime, endtime;
265 int audio_ahead = 0;
266 unsigned pts_ahead_val = SYSTIME_CORRECTION_THRESHOLD;
267 int diff;
268 int sync_switch_ms = 200; // ms
269 int count = 0;
270
271 unsigned long cur_pcr;
272 struct am_io_param am_io;
273
274 starttime = gettime();
275
276 int samplerate = 0;
277 int channels = 0;
278 //ARM based decoder,should got from decoder
279 adec_print("adec_pts_droppcm start get audio sr/ch info \n");
280 while (!audec->need_stop) {
281 if (audec->g_bst) {
282 samplerate = audec->g_bst->samplerate;
283 channels = audec->g_bst->channels;
284 }
285 //DSP decoder must have got audio info when feeder_init
286 else {
287 samplerate = audec->samplerate;
288 channels = audec->channels;
289 }
290 if (!samplerate || !channels) {
291 amthreadpool_thread_usleep(10000);
292 continue;
293 }
294 break;
295 }
296 adec_print("adec_pts_droppcm get audio sr/ch info done sr %d, ch %d \n", samplerate, channels);
297
298 // drop pcm according to media.amplayer.dropms
299 memset(value, 0, sizeof(value));
300 if (property_get("media.amplayer.dropms", value, NULL) > 0) {
301 dropms = atoi(value);
302 audec->droppcm_ms = dropms;
303 drop_size = dropms * (audec->samplerate / 1000) * audec->channels * 2;
304 if (drop_size > 0) {
305 if (droppcm_use_size(audec, drop_size) == -1) {
306 adec_print("[%s::%d] data not enough, drop failed! \n", __FUNCTION__, __LINE__);
307 }
308
309 if (am_getconfig_bool("media.amplayer.dropmsquit")) {
310 adec_print("[%s::%d] fast droppcm: %d ms! \n", __FUNCTION__, __LINE__, dropms);
311 return 0;
312 }
313 }
314 }
315
316 // pre drop, according to first check in vpts
317
318 adec_print("[%s::%d] start pre drop ! \n", __FUNCTION__, __LINE__);
319 if (am_getconfig_bool("media.amplayer.pre_droppcm")) {
320 unsigned long checkin_firstvpts = 0;
321 while (!checkin_firstvpts) {
322 if (audec->need_stop) {
323 return 0;
324 }
325 if (sysfs_get_int(TSYNC_CHECKIN_FIRSTVPTS, &checkin_firstvpts) == -1) {
326 adec_print("## [%s::%d] unable to get TSYNC_CHECKIN_FIRSTVPTS! \n", __FUNCTION__, __LINE__);
327 return -1;
328 }
329 if (count >= 50) {
330 adec_print("Unable to get checkin_firstvpts, failed to pre_droppcm\n");
331 break;
332 } else if (checkin_firstvpts) {
333 adec_print("get checkin_firstvpts, checkin_firstvpts=0x%x\n",checkin_firstvpts);
334 break;
335 }
336 count++;
337 amthreadpool_thread_usleep(20000); // 20ms
338 }
339 if (checkin_firstvpts) {
340 apts = adec_calc_pts(audec);
341 diff = (apts > checkin_firstvpts) ? (apts - checkin_firstvpts) : (checkin_firstvpts - apts);
342 adec_print("before drop pre --apts 0x%x,checkin_firstvpts 0x%x,apts %s, diff 0x%x\n", apts, checkin_firstvpts, (apts > checkin_firstvpts) ? "big" : "small", diff);
343 if ((apts < checkin_firstvpts) && (diff < DROP_PCM_PTS_DIFF_THRESHHOLD)) {
344 droppts = checkin_firstvpts - apts;
345 audec->droppcm_ms = droppts / 90;
346 drop_size = (droppts / 90) * (audec->samplerate / 1000) * audec->channels * 2;
347 adec_print("[%s::%d]pre audec->samplerated = %d, audec->channels = %d! \n", __FUNCTION__, __LINE__, audec->samplerate, audec->channels);
348 adec_print("[%s::%d]pre droppts:0x%x, drop_size=%d, audio ahead %d,ahead pts value %d \n", __FUNCTION__, __LINE__,
349 droppts, drop_size, audio_ahead, pts_ahead_val);
350 if (droppcm_use_size(audec, drop_size) == -1) {
351 adec_print("[%s::%d] timeout! data not enough! \n", __FUNCTION__, __LINE__);
352 }
353 oldapts = apts;
354 apts = adec_calc_pts(audec);
355 diff = (apts > checkin_firstvpts) ? (apts - checkin_firstvpts) : (checkin_firstvpts - apts);
356 adec_print("after drop pre:--apts 0x%x,droped:0x%x, checkin_firstvpts 0x%x,apts %s, diff 0x%x\n", apts, apts - oldapts, checkin_firstvpts, (apts > checkin_firstvpts) ? "big" : "small", diff);
357 }
358 }
359 }
360
361 if (droppcm_get_refpts(audec, &refpts) == -1) {
362 adec_print("[%s::%d] get refpts failed! \n", __FUNCTION__, __LINE__);
363 return -1;
364 }
365
366 while (!audec->first_apts) {
367 unsigned long first_apts = 0;
368
369 if (audec->need_stop) {
370 return 0;
371 }
372
373 if (count > 10) {
374 break;
375 }
376
377 first_apts = adec_calc_pts(audec);
378
379 if (sysfs_get_int(TSYNC_FIRSTAPTS, &audec->first_apts) == -1) {
380 adec_print("## [%s::%d] unable to get first_apts! \n", __FUNCTION__, __LINE__);
381 return -1;
382 }
383 count++;
384 amthreadpool_thread_usleep(50000); // 50ms
385 adec_print("wait audec->first_apts first_apts = 0x%x, audec->first_apts = 0x%x\n", first_apts, audec->first_apts);
386 }
387 diff = (audec->first_apts > refpts) ? (audec->first_apts - refpts) : (refpts - audec->first_apts);
388 adec_print("before drop --audec->first_apts 0x%x,refpts 0x%x,audec->first_apts %s, diff 0x%x\n", audec->first_apts, refpts, (audec->first_apts > refpts) ? "big" : "small", diff);
389 {
390 sysfs_get_int(TSYNC_PCRSCR, &cur_pcr);
391 ioctl(audec->adsp_ops.amstream_fd, AMSTREAM_IOC_AB_STATUS, (unsigned long)&am_io);
392 adec_print("before drop ab_level=%x, cur_pcr=%x", am_io.status.data_len, cur_pcr);
393 }
394 if (property_get("media.amplayer.sync_switch_ms", value, NULL) > 0) {
395 sync_switch_ms = atoi(value);
396 }
397
398 if (am_getconfig_bool("media.libplayer.show_firstframe") &&
399 audec->tsync_mode == TSYNC_MODE_PCRMASTER) {
400 const char * show_first_frame = "/sys/class/video/show_first_frame_nosync";
401 amsysfs_set_sysfs_int(show_first_frame, 1);
402 sync_switch_ms = 10000;//10s
403 }
404 adec_print("sync switch setting: %d ms \n", sync_switch_ms);
405 //auto switch -- if diff not too much, using slow sync
406 if (audec->first_apts >= refpts || diff / 90 < sync_switch_ms) {
407 //enable_slowsync_repeate();
408 adec_print("diff less than %d (ms), use slowsync repeate mode \n", sync_switch_ms);
409 return 0;
410 }
411 //when start to play,may audio discontinue happens, in this case, don't drop pcm operation
412#if 1
413 else if (diff > DROP_PCM_PTS_DIFF_THRESHHOLD) {
414 adec_print("pts diff 0x%x bigger than %d (ms), don't drop pcm \n", diff, DROP_PCM_PTS_DIFF_THRESHHOLD * 1000 / 90000);
415 return 0;
416 }
417#endif
418 // calculate ahead pcm size
419 droppcm_prop_ctrl(&audio_ahead, &pts_ahead_val);
420
421 // drop pcm
422 droppts = refpts - audec->first_apts + pts_ahead_val * audio_ahead;
423 audec->droppcm_ms = droppts / 90;
424 drop_size = (droppts / 90) * (audec->samplerate / 1000) * audec->channels * 2;
425 adec_print("[%s::%d] audec->samplerated = %d, audec->channels = %d! \n", __FUNCTION__, __LINE__, audec->samplerate, audec->channels);
426 adec_print("[%s::%d] droppts:0x%x, drop_size=%d, audio ahead %d,ahead pts value %d \n", __FUNCTION__, __LINE__,
427 droppts, drop_size, audio_ahead, pts_ahead_val);
428 if (droppcm_use_size(audec, drop_size) == -1) {
429 adec_print("[%s::%d] timeout! data not enough! \n", __FUNCTION__, __LINE__);
430 }
431
432 // show apts refpts after droppcm
433 if (sysfs_get_int(TSYNC_VPTS, &refpts) == -1) {
434 adec_print("## [%s::%d] unable to get vpts! \n", __FUNCTION__, __LINE__);
435 return -1;
436 }
437
438 oldapts = audec->first_apts;
439 apts = adec_calc_pts(audec);
440 diff = (apts > refpts) ? (apts - refpts) : (refpts - apts);
441 adec_print("after drop:--apts 0x%x,droped:0x%x, vpts 0x%x,apts %s, diff 0x%x\n", apts, apts - oldapts, refpts, (apts > refpts) ? "big" : "small", diff);
442 if (diff > DROP_PCM_RESET_PCR_THRESHOLD){
443 char buf[64];
444 sprintf(buf, "0x%lx", apts);
445 adec_print("## [%s::%d] reset pcr =0x%x \n", __FUNCTION__, __LINE__);
446 if (amsysfs_set_sysfs_str(TSYNC_PCRSCR, buf)){
447 adec_print("## [%s::%d] reset pcr error \n", __FUNCTION__, __LINE__);
448 }
449 }
450
451 {
452 sysfs_get_int(TSYNC_PCRSCR, &cur_pcr);
453 ioctl(audec->adsp_ops.amstream_fd, AMSTREAM_IOC_AB_STATUS, (unsigned long)&am_io);
454 adec_print("after drop ab_level=%x, cur_pcr=%x", am_io.status.data_len, cur_pcr);
455 }
456
457 endtime = gettime();
458 adec_print("==starttime is :%lld ms endtime is:%lld ms usetime:%lld ms \n", starttime / 1000 , endtime / 1000 , (endtime - starttime) / 1000);
459
460 return 0;
461}
462
463/**
464 * \brief pause pts manager
465 * \return 0 on success otherwise -1
466 */
467int adec_pts_pause(void)
468{
469 adec_print("adec_pts_pause");
470 return amsysfs_set_sysfs_str(TSYNC_EVENT, "AUDIO_PAUSE");
471}
472
473/**
474 * \brief resume pts manager
475 * \return 0 on success otherwise -1
476 */
477int adec_pts_resume(void)
478{
479 adec_print("adec_pts_resume");
480 return amsysfs_set_sysfs_str(TSYNC_EVENT, "AUDIO_RESUME");
481
482}
483
484/**
485 * \brief refresh current audio pts
486 * \param audec pointer to audec
487 * \return 0 on success otherwise -1
488 */
489static int apts_interrupt = 0;
490static int pcrmaster_droppcm_flag = 0;
491static int pre_filltime = -1;
492int adec_refresh_pts(aml_audio_dec_t *audec)
493{
494 unsigned long pts;
495 unsigned long systime;
496 unsigned long last_pts = audec->adsp_ops.last_audio_pts;
497 unsigned long last_kernel_pts = audec->adsp_ops.kernel_audio_pts;
498 int apts_start_flag = 0;//store the last flag
499 int samplerate = 48000;
500 int channels = 2;
501 char buf[64];
502 char ret_val = -1;
503 if (audec->auto_mute == 1) {
504 return 0;
505 }
506 if (pre_filltime == -1) {
507 char value[PROPERTY_VALUE_MAX] = {0};
508 if (property_get("media.amadec.prefilltime", value, NULL) > 0) {
509 pre_filltime = atoi(value);
510 } else {
511 pre_filltime = 170;
512 }
513 adec_print("[%s:%d] amadec- pre_filltime:%d ms. \n", __FUNCTION__, __LINE__, pre_filltime);
514 }
515
516 apts_start_flag = audec->apts_start_flag;
517 //if the audio start has not been triggered to tsync,calculate the audio pcm data which writen to audiotrack
518 if (!audec->apts_start_flag) {
519 int latency;
520 int wait = pre_filltime;
521 if (audec->g_bst) {
522 samplerate = audec->g_bst->samplerate;
523 channels = audec->g_bst->channels;
524 }
525 //DSP decoder must have got audio info when feeder_init
526 else {
527 samplerate = audec->samplerate;
528 channels = audec->channels;
529 }
530 // 170 ms audio hal have triggered the output hw.
531 latency = audec->aout_ops.latency(audec);
532 if (latency > 0 && ((audec->pcm_bytes_readed * 1000 / (samplerate * channels * 2)) >= wait)) {
533 adec_print("unable to getsystime--\n\n [[[%lld,%d,%d,%d,%d]]]\n",
534 audec->pcm_bytes_readed
535 ,samplerate
536 ,channels
537 ,wait,
538 latency);
539 audec->apts_start_flag = 1;
540 if (!am_getconfig_bool("libplayer.slowsync.disable"))
541 enable_slowsync_repeate();
542 }
543 }
544 memset(buf, 0, sizeof(buf));
545
546 systime = audec->adsp_ops.get_cur_pcrscr(&audec->adsp_ops);
547 if (systime == -1) {
548 adec_print("unable to getsystime");
549 audec->pcrscr64 = 0;
550 return -1;
551 }
552
553 /* get audio time stamp */
554 pts = adec_calc_pts(audec);
555 if (pts != -1 && (apts_start_flag != audec->apts_start_flag)) {
556 adec_print("audio pts start from 0x%lx", pts);
557 sprintf(buf, "AUDIO_START:0x%lx", pts);
558 if (amsysfs_set_sysfs_str(TSYNC_EVENT, buf) == -1) {
559 return -1;
560 }
561 }
562 if (pts == -1 || last_pts == pts) {
563 //close(fd);
564 //if (pts == -1) {
565 audec->pcrscr64 = (int64_t)systime;
566 return -1;
567 //}
568 }
569#if 1
570 unsigned int u32_vpts = mysysfs_get_sysfs_int16(TSYNC_VPTS);
571 unsigned int last_checkin_apts = mysysfs_get_sysfs_int16(TSYNC_LAST_CHECKIN_APTS);
572 //int play_mode = mysysfs_get_sysfs_int(TSYNC_PCR_PLAY_MODE);
573
574 if (audec->tsync_mode == TSYNC_MODE_PCRMASTER && audec->pcrtsync_enable
575 && ((((int64_t)pts) - audec->last_apts64 > TIME_UNIT90K / 10) || ((int64_t)pts < audec->last_apts64))) {
576
577 int64_t apts64 = (int64_t)pts;
578 int64_t pcrscr64 = (int64_t)systime;
579 audec->apts64 = apts64;
580 audec->pcrscr64 = pcrscr64;
581
582 if (audec->adis_flag && abs(audec->pcrscr64 - audec->last_apts64) > APTS_DISCONTINUE_THRESHOLD) {
583 audec->adis_flag = 0;
584 adec_print("[%s:%d] pcr discontinue: last_pcr:%llx, pcr:%llx, --\n", __FUNCTION__, __LINE__, audec->last_pcrscr64, audec->pcrscr64);
585 }
586 audec->last_pcrscr64 = pcrscr64;
587 if (apts64 < audec->last_apts64) {
588 audec->last_apts64 = apts64;
589 }
590
591 unsigned int adiff = (unsigned int)((int64_t)last_checkin_apts - apts64);
592 adec_print("## tsync_mode:%d, pcr:%llx,apts:%llx, u32_vpts = 0x%x,lastapts:%llx, flag:%d,%d,---\n",
593 audec->tsync_mode, pcrscr64, apts64, u32_vpts, audec->last_apts64, pcrmaster_droppcm_flag, audec->adis_flag);
594 //adec_print("## tsync_mode:%d,apts:%llx,last_checkin_apts=0x%x,diff=%ld, play_mode=%d\n",
595 // audec->tsync_mode, apts64, last_checkin_apts, adiff, play_mode);
596 // drop pcm
597 if (pcrscr64 - apts64 > audec->pcrmaster_droppcm_thsh && abs(pcrscr64 - apts64) < 3 * 90000 && abs(u32_vpts - apts64) >= 45000) {
598 if (pcrmaster_droppcm_flag++ > 20) {
599 int drop_size, droppts;
600 droppts = pcrscr64 - apts64;
601 audec->droppcm_ms = droppts / 90;
602 drop_size = (droppts / 90) * (audec->samplerate / 1000) * audec->channels * 2;
603 pcrmaster_droppcm_flag = 0;
604 adec_print("## pcrmaster, droppcm pcr:%lx,apts:%lx,lastapts:%lx,---\n", systime, pts, last_pts);
605
606 if (droppcm_use_size(audec, drop_size) == -1) {
607 adec_print("[%s::%d] timeout! data not enough! \n", __FUNCTION__, __LINE__);
608 }
609 }
610 } else {
611 pcrmaster_droppcm_flag = 0;
612 }
613 }
614#endif
615 if ((abs(pts - last_pts) > APTS_DISCONTINUE_THRESHOLD) && (audec->adsp_ops.last_pts_valid)) {
616 /* report audio time interruption */
617 adec_print("pts = %lx, last pts = %lx, u32_vpts=0x%x, pcr=0x%lx\n", pts, last_pts, u32_vpts, systime);
618
619 adec_print("audio time interrupt: 0x%lx->0x%lx, 0x%lx\n", last_pts, pts, abs(pts - last_pts));
620 int tsync_pcr_discontinue = 0;
621 unsigned int adiff = (unsigned int)((unsigned long)last_checkin_apts - pts);
622 if (audec->tsync_mode == TSYNC_MODE_PCRMASTER) {
623 tsync_pcr_discontinue = mysysfs_get_sysfs_int16(TSYNC_PCR_DISCONTINUE);
624 adec_print("%s,tsync_pcr_discontinue=0x%x-\n",__FUNCTION__,tsync_pcr_discontinue);
625 //adec_print("audio interrupt:%d,apts:%llx,last_checkin_apts=0x%x,diff=%ld, play_mode=%d\n",
626 // audec->tsync_mode, pts, last_checkin_apts, adiff,play_mode);
627
628 }
629 if (audec->tsync_mode == TSYNC_MODE_PCRMASTER && audec->pcrtsync_enable && (tsync_pcr_discontinue & VIDEO_DISCONTINUE)) {
630 unsigned long tsync_pcr_dispoint = 0;
631 int count = 50;
632 audec->apts64 = (int64_t)pts;
633 audec->adis_flag = 0;
634
635 do {
636 if (sysfs_get_int(TSYNC_PCR_DISPOINT, &tsync_pcr_dispoint) == -1) {
637 adec_print("## [%s::%d] unable to get TSYNC_PCR_DISPOINT! \n", __FUNCTION__, __LINE__);
638 audec->adis_flag = 100;
639 break;
640 }
641 amthreadpool_thread_usleep(20000);
642 count--;
643 } while (tsync_pcr_dispoint == 0 && count > 0);
644
645 if (tsync_pcr_dispoint != 0) {
646 int64_t apts64 = (int64_t)pts;
647 int64_t pcrscr64 = (int64_t)tsync_pcr_dispoint;
648 audec->pcrscr64 = (int64_t)pcrscr64;
649 audec->tsync_pcr_dispoint = (int64_t)tsync_pcr_dispoint;
650 audec->adis_flag = 100;
651
652 adec_print("## pcrmaster, tsync_pcr_dispoint,pcr:%lx,apts:%lx,lastapts:%lx,---\n", tsync_pcr_dispoint, pts, last_pts);
653 // drop pcm, if larger than 10s, not to drop pcm
654 if (pcrscr64 - apts64 > APTS_DISCONTINUE_THRESHOLD && pcrscr64 - apts64 < 10 * 90000) {
655 int drop_size, droppts;
656 droppts = pcrscr64 - apts64;
657
658 audec->droppcm_ms = droppts / 90;
659
660 drop_size = (droppts / 90) * (audec->samplerate / 1000) * audec->channels * 2;
661 adec_print("## pcrmaster, droppcm pcr:%lx,apts:%lx,lastapts:%lx,---\n", systime, pts, last_pts);
662
663 if (droppcm_use_size(audec, drop_size) == -1) {
664 adec_print("[%s::%d] timeout! data not enough! \n", __FUNCTION__, __LINE__);
665 }
666 }
667 }
668 }
669
670 sprintf(buf, "AUDIO_TSTAMP_DISCONTINUITY:0x%lx", pts);
671
672 if (amsysfs_set_sysfs_str(TSYNC_EVENT, buf) == -1) {
673 adec_print("unable to open file %s,err: %s", TSYNC_EVENT, strerror(errno));
674 return -1;
675 }
676
677 audec->adsp_ops.last_audio_pts = pts;
678 audec->adsp_ops.last_pts_valid = 1;
679 adec_print("[%s:%d]set automute orig %d!\n", __FUNCTION__, __LINE__, audec->auto_mute);
680 audec->auto_mute = 0;
681 apts_interrupt = 5;
682 return 0;
683 }
684
685 if (last_kernel_pts == audec->adsp_ops.kernel_audio_pts) {
686 audec->pcrscr64 = (int64_t)systime;
687 return 0;
688 }
689
690 audec->adsp_ops.last_audio_pts = pts;
691 audec->adsp_ops.last_pts_valid = 1;
692
693 if (abs(pts - systime) < audec->avsync_threshold) {
694 apts_interrupt = 0;
695 return 0;
696 } else if (apts_interrupt > 0) {
697 apts_interrupt --;
698 return 0;
699 }
700
701 /* report apts-system time difference */
702 if (!apts_start_flag) {
703 return 0;
704 }
705
706 {/*add by zz*/
707 /*
708 reget pts to make sure pts is calc has no errors.
709 because we may have accuracy problem on
710 many thread update the pts related infos.
711 */
712 unsigned long re_getpts = adec_calc_pts(audec);
713 if (abs(pts - re_getpts) > 900) { /*100 ms * 10%*/
714 /*ignore this diff.*/
715 adec_print("## [%s::%d] ixet apts: %d ,%d \n",
716 __FUNCTION__, __LINE__,
717 pts, re_getpts);
718 return 0;
719 } else {
720 /*used new pts.*/
721 pts = re_getpts;
722 }
723 }
724 if (audec->refresh_pts_readytime_ms > 0) {
725 /*pts_readytime not reached ,wait and delay reset apts.*/
726 if (audec->refresh_pts_readytime_ms > gettime()/1000)
727 return 0;
728 audec->refresh_pts_readytime_ms = 0;
729 }
730#if 0
731 if (audec->apts_reset_scr_delay_ms > 0) {
732 unsigned long vpts = 0;
733 if ((vpts = mysysfs_get_sysfs_int16(TSYNC_VPTS)) < 0) {
734 adec_print("## [%s::%d] unable to get vpts! \n", __FUNCTION__, __LINE__);
735 return -1;
736 }
737 //adec_print("vpts %x,last apts %x \n,diff %x \n",vpts,audec->last_checkout_apts,abs(vpts-audec->last_discontinue_apts));
738 if ((gettime() - audec->last_discontinue_time) < audec->apts_reset_scr_delay_ms * 1000 && (abs(vpts - audec->last_discontinue_apts) > audec->avsync_threshold)) {
739 return 0;
740 } else {
741 adec_print("after %lld ms,apts reset scr delay time out \n", (gettime() - audec->last_discontinue_time) / 1000);
742 audec->apts_reset_scr_delay_ms = 0;
743 }
744 } else if (abs(pts - last_pts) >= 90000 && abs(pts - last_pts) < APTS_DISCONTINUE_THRESHOLD) {
745 audec->last_discontinue_time = gettime();
746 audec->last_discontinue_apts = pts;
747 audec->apts_reset_scr_delay_ms = audio_get_decoded_pcm_delay(audec)/*+audec->aout_ops.latency(audec)+100*/;
748 adec_print("apts reset time delay %d ms,pts diff 0x%x,timestamp %d ms \n", audec->apts_reset_scr_delay_ms, abs(pts - last_pts),
749 abs(pts - last_pts) / 90);
750 return 0;
751 }
752#endif
753
754 if (audec->adsp_ops.set_cur_apts) {
755 ret_val = audec->adsp_ops.set_cur_apts(&audec->adsp_ops, pts);
756 } else {
757 sprintf(buf, "0x%lx", pts);
758 ret_val = amsysfs_set_sysfs_str(TSYNC_APTS, buf);
759 }
760 if (ret_val == -1) {
761 adec_print("unable to open file %s,err: %s", TSYNC_APTS, strerror(errno));
762 return -1;
763 }
764 if (abs(pts - systime) >= 90000 / 10) {
765 //adec_print("report apts as 0x%x,system pts=0x%x, difference= %ld\n", pts, systime, (pts - systime));
766 }
767 return 0;
768}
769
770/**
771 * \brief Disable or Enable av sync
772 * \param e 1 = enable, 0 = disable
773 * \return 0 on success otherwise -1
774 */
775int avsync_en(int e)
776{
777 return amsysfs_set_sysfs_int(TSYNC_ENABLE, e);
778}
779
780/**
781 * \brief calc pts when switch audio track
782 * \param audec pointer to audec
783 * \return 0 on success otherwise -1
784 *
785 * When audio track switch occurred, use this function to judge audio should
786 * be played or not. If system time fall behind audio pts , and their difference
787 * is greater than SYSTIME_CORRECTION_THRESHOLD, auido should wait for
788 * video. Otherwise audio can be played.
789 */
790int track_switch_pts(aml_audio_dec_t *audec)
791{
792 unsigned long vpts;
793 unsigned long apts;
794 unsigned long pcr;
795 char buf[32];
796
797 memset(buf, 0, sizeof(buf));
798
799 pcr = audec->adsp_ops.get_cur_pcrscr(&audec->adsp_ops);
800 if (pcr == -1) {
801 adec_print("unable to get pcr");
802 return 1;
803 }
804
805 apts = adec_calc_pts(audec);
806 if (apts == -1) {
807 adec_print("unable to get apts");
808 return 1;
809 }
810
811 if ((apts > pcr) && (apts - pcr > 0x100000)) {
812 return 0;
813 }
814
815 if (abs(apts - pcr) < audec->avsync_threshold || (apts <= pcr)) {
816 return 0;
817 } else {
818 return 1;
819 }
820
821}
822static int vdec_pts_pause(void)
823{
824 char *path = "/sys/class/video_pause";
825 return amsysfs_set_sysfs_int(path, 1);
826
827}
828int vdec_pts_resume(void)
829{
830 adec_print("vdec_pts_resume\n");
831 return amsysfs_set_sysfs_str(TSYNC_EVENT, "VIDEO_PAUSE:0x0");
832}
833
834#define DROPPCM_TMPBUF_SIZE (8*1024)
835int droppcm_use_size(aml_audio_dec_t *audec, int drop_size)
836{
837 char value[PROPERTY_VALUE_MAX] = {0};
838 char buffer[DROPPCM_TMPBUF_SIZE];
839 int drop_duration = drop_size / audec->channels / 2 / audec->samplerate;
840 int nDropCount = 0;
841 int size = drop_size;
842 int ret = 0;
843 int drop_max_time = DROP_PCM_MAX_TIME; // unit:ms
844 int64_t start_time, nDropConsumeTime;
845 char platformtype[20];
846 char *buffer_raw = NULL;
847 int drop_raw = 0;
848 int drop_raw_size = 0;
849 int nDropCount_raw = 0;
850 if (audec->codec_type > 0) {
851 buffer_raw = malloc(DROPPCM_TMPBUF_SIZE * audec->codec_type);
852 if (buffer_raw == NULL) {
853 adec_print("[%s %d]WARNING:malloc memory for buffer_raw failed!\n", __FUNCTION__, __LINE__);
854 } else {
855 drop_raw = 1;
856 }
857 }
858 memset(platformtype, 0, sizeof(platformtype));
859 memset(value, 0, sizeof(value));
860 if (property_get("media.amplayer.dropmaxtime", value, NULL) > 0) {
861 drop_max_time = atoi(value);
862 }
863
864 if (audec->droppcm_ms > 50) {
865 drop_max_time = audec->droppcm_ms - 50;
866 }
867 memset(value, 0, sizeof(value));
868 if (property_get("ro.board.platform", value, NULL) > 0) {
869 if (match_types("meson6", value)) {
870 memcpy(platformtype, "meson6", 6);
871 } else if (match_types("meson8", value)) {
872 memcpy(platformtype, "meson8", 6);
873 }
874 }
875
876 start_time = gettime();
877 adec_print("before droppcm: drop_size=%d, nDropCount:%d, drop_max_time:%d,platform:%s, ---\n", drop_size, nDropCount, drop_max_time, platformtype);
878 while (drop_size > 0 && !audec->need_stop/*&& drop_duration < DROP_PCM_DURATION_THRESHHOLD*/) {
879 ret = audec->adsp_ops.dsp_read(&audec->adsp_ops, buffer, MIN(drop_size, DROPPCM_TMPBUF_SIZE));
880 if (drop_raw > 0 && ret > 0) {
881 drop_raw_size = ret * audec->codec_type;
882 nDropCount_raw = 0;
883 while (drop_raw_size > 0) {
884 drop_raw_size -= audec->adsp_ops.dsp_read_raw(&audec->adsp_ops, buffer_raw, drop_raw_size);
885 nDropCount_raw++;
886 if (nDropCount_raw > 10) {
887 adec_print("[%s %d]WARNING:no enough rawdata/%d to Drop,break!\n", __FUNCTION__, __LINE__, drop_raw_size);
888 break;
889 }
890 }
891 }
892 //apts = adec_calc_pts(audec);
893 //adec_print("==drop_size=%d, ret=%d, nDropCount:%d apts=0x%x,-----------------\n",drop_size, ret, nDropCount,apts);
894 nDropConsumeTime = gettime() - start_time;
895 if (nDropConsumeTime / 1000 > drop_max_time) {
896 adec_print("==ret:%d no pcm nDropCount:%d ,nDropConsumeTime:%lld reached drop_max_time:%d, \n", ret, nDropCount, nDropConsumeTime / 1000, drop_max_time);
897 drop_size -= ret;
898 ret = -1;
899 break;
900 }
901 if (ret == 0) { //no data in pcm buf
902 if (nDropCount >= 40) {
903 ret = -1;
904 break;
905 } else {
906 nDropCount++;
907 }
908 if (!strcmp(platformtype, "messon8")) {
909 amthreadpool_thread_usleep(50000); // 10ms
910 } else {
911 amthreadpool_thread_usleep(50000); // 50ms
912 }
913 adec_print("==ret:0 no pcm nDropCount:%d \n", nDropCount);
914 } else {
915 nDropCount = 0;
916 drop_size -= ret;
917 }
918 }
919 if (buffer_raw != NULL) {
920 free(buffer_raw);
921 }
922 adec_print("after droppcm: drop_size=%d, droped:%d, nDropConsumeTime:%lld us,---\n", drop_size, size - drop_size, nDropConsumeTime);
923
924 return ret;
925}
926
927void droppcm_prop_ctrl(int *audio_ahead, int *pts_ahead_val)
928{
929 char value[PROPERTY_VALUE_MAX] = {0};
930
931 if (am_getconfig_bool("media.libplayer.wfd")) {
932 *pts_ahead_val = *pts_ahead_val * 2 / 3;
933 }
934
935 if (property_get("media.amplayer.apts", value, NULL) > 0) {
936 if (!strcmp(value, "slow")) {
937 *audio_ahead = -1;
938 } else if (!strcmp(value, "fast")) {
939 *audio_ahead = 1;
940 }
941 }
942 memset(value, 0, sizeof(value));
943 if (property_get("media.amplayer.apts_val", value, NULL) > 0) {
944 *pts_ahead_val = atoi(value);
945 }
946}
947
948int droppcm_get_refpts(aml_audio_dec_t *audec, unsigned long *refpts)
949{
950 char value[PROPERTY_VALUE_MAX] = {0};
951 char buf[32];
952 char tsync_mode_str[10];
953 int tsync_mode;
954 int circount = 3000; // default: 3000ms
955 int refmode = TSYNC_MODE_AMASTER;
956 int64_t start_time = gettime();
957 unsigned long firstvpts = 0;
958 unsigned long cur_vpts = 0;
959 audio_out_operations_t * aout_ops = &audec->aout_ops;
960 if (amsysfs_get_sysfs_str(TSYNC_MODE, buf, sizeof(buf)) == -1) {
961 adec_print("unable to get tsync_mode from: %s", buf);
962 return -1;
963 }
964 if (sscanf(buf, "%d: %s", &tsync_mode, tsync_mode_str) < 1) {
965 adec_print("unable to get tsync_mode from: %s", buf);
966 return -1;
967 }
968 if ((tsync_mode == TSYNC_MODE_AMASTER && !strcmp(tsync_mode_str, "amaster"))
969 || (tsync_mode == TSYNC_MODE_VMASTER && !strcmp(tsync_mode_str, "vmaster") && audec->droppcm_flag)/* switch audio flag, firstvpts is unvalid when switch audio*/) {
970 refmode = TSYNC_MODE_AMASTER;
971 } else if (tsync_mode == TSYNC_MODE_VMASTER && !strcmp(tsync_mode_str, "vmaster") && !audec->droppcm_flag) {
972 refmode = TSYNC_MODE_VMASTER;
973 } else if (tsync_mode == TSYNC_MODE_PCRMASTER && !strcmp(tsync_mode_str, "pcrmaster")) {
974 refmode = TSYNC_MODE_PCRMASTER;
975 }
976
977 adec_print("## [%s::%d] refmode:%d, tsync_mode:%d,%s, droppcm_flag:%d, ---\n", __FUNCTION__, __LINE__,
978 refmode, tsync_mode, tsync_mode_str, audec->droppcm_flag);
979 if (refmode == TSYNC_MODE_AMASTER || refmode == TSYNC_MODE_VMASTER) {
980 if (sysfs_get_int(TSYNC_VPTS, refpts) == -1) {
981 adec_print("## [%s::%d] unable to get vpts! \n", __FUNCTION__, __LINE__);
982 return -1;
983 }
984 adec_print("## [%s::%d] default vpts:0x%x, ---\n", __FUNCTION__, __LINE__, *refpts);
985 } else if (tsync_mode == TSYNC_MODE_PCRMASTER && !strcmp(tsync_mode_str, "pcrmaster")) {
986 if (sysfs_get_int(TSYNC_PCRSCR, refpts) == -1) {
987 adec_print("## [%s::%d] unable to get pts_pcrscr! \n", __FUNCTION__, __LINE__);
988 return -1;
989 }
990 int wait_count = 0;
991 while ((*refpts) == 0) {
992 if (audec->need_stop) {
993 return 0;
994 }
995 sysfs_get_int(TSYNC_PCRSCR, refpts);
996 //amthreadpool_thread_usleep(100000);
997 wait_count++;
998 adec_print("## [%s::%d] wait_count = %d, refpts = 0x%x ---\n", __FUNCTION__, __LINE__, wait_count, *refpts);
999 if (wait_count == 1) { //wait 2s
1000 break;
1001 }
1002 }
1003 adec_print("## [%s::%d] pcrmaster, refpts:0x%x, ---\n", __FUNCTION__, __LINE__, *refpts);
1004 }
1005
1006 memset(value, 0, sizeof(value));
1007 if (property_get("media.amplayer.dropwaitxms", value, NULL) > 0) {
1008 circount = atoi(value);
1009 }
1010 adec_print("drop wait max ms = %d \n", circount);
1011
1012 //media.amplayer.refmode : 0 vpts 1 other case
1013#if 0
1014 int use_vpts = 1;
1015 if (property_get("media.amplayer.refmode", value, NULL) > 0) {
1016 if (atoi(value) != 0) {
1017 use_vpts = 0;
1018 }
1019 }
1020
1021 if (use_vpts == 0) {
1022 return 0;
1023 }
1024 adec_print("drop pcm use_vpts = %d \n", use_vpts);
1025#endif
1026
1027 unsigned long checkin_firstvpts = 0;
1028 while ((!firstvpts || !checkin_firstvpts)) {
1029 if (audec->need_stop) {
1030 return 0;
1031 }
1032 aout_ops = &audec->aout_ops;
1033 if (aout_ops) {
1034 /*cts if audio track rate is set,skip */
1035 if (aout_ops->track_rate != 8.8f)
1036 return 0;
1037 }
1038 if (sysfs_get_int(TSYNC_FIRSTVPTS, &firstvpts) == -1) {
1039 adec_print("## [%s::%d] unable to get firstpts! \n", __FUNCTION__, __LINE__);
1040 return -1;
1041 }
1042
1043 if (sysfs_get_int(TSYNC_CHECKIN_FIRSTVPTS, &checkin_firstvpts) == -1) {
1044 adec_print("## [%s::%d] unable to get TSYNC_CHECKIN_FIRSTVPTS! \n", __FUNCTION__, __LINE__);
1045 return -1;
1046 }
1047
1048 if (gettime() - start_time >= (circount * 1000)) {
1049 adec_print("## [%s::%d] max time reached! %d ms \n", __FUNCTION__, __LINE__, circount);
1050 break;
1051 }
1052 amthreadpool_thread_usleep(10000); // 10ms
1053 }
1054 adec_print("## [%s::%d] firstvpts:0x%x, use:%lld us, maxtime:%d ms, ---\n", __FUNCTION__, __LINE__, firstvpts, gettime() - start_time, circount);
1055
1056 if (sysfs_get_int(TSYNC_VPTS, &cur_vpts) == -1) {
1057 adec_print("## [%s::%d] unable to get vpts! \n", __FUNCTION__, __LINE__);
1058 return -1;
1059 }
1060
1061 if (audec->tsync_mode == TSYNC_MODE_PCRMASTER) {
1062 if (cur_vpts && cur_vpts < firstvpts && cur_vpts != checkin_firstvpts) {
1063 *refpts = cur_vpts;
1064 } else if (firstvpts) {
1065 *refpts = firstvpts;
1066 } else {
1067 *refpts = checkin_firstvpts;
1068 }
1069 } else {
1070 if (firstvpts) {
1071 *refpts = firstvpts;
1072 } else {
1073 *refpts = cur_vpts;
1074 }
1075 }
1076 adec_print("## [%s::%d] cur_vpts:0x%x,checkin_firstvpts=0x%x,firstvpts:0x%x refpts:0x%x, ---\n",
1077 __FUNCTION__, __LINE__, cur_vpts, checkin_firstvpts, firstvpts, *refpts);
1078
1079
1080 return 0;
1081}
1082
1083int adec_get_tsync_info(int *tsync_mode)
1084{
1085 char value[PROPERTY_VALUE_MAX] = {0};
1086 char buf[32];
1087 char tsync_mode_str[10];
1088
1089 if (amsysfs_get_sysfs_str(TSYNC_MODE, buf, sizeof(buf)) == -1) {
1090 adec_print("unable to get tsync_mode from: %s", buf);
1091 return -1;
1092 }
1093 if (sscanf(buf, "%d: %s", tsync_mode, tsync_mode_str) < 1) {
1094 adec_print("unable to get tsync_mode from: %s", buf);
1095 return -1;
1096 }
1097
1098 if (tsync_mode == TSYNC_MODE_AMASTER && !strcmp(tsync_mode_str, "amaster")) {
1099 *tsync_mode = TSYNC_MODE_AMASTER;
1100 } else if (tsync_mode == TSYNC_MODE_VMASTER && !strcmp(tsync_mode_str, "vmaster")) {
1101 *tsync_mode = TSYNC_MODE_VMASTER;
1102 } else if (tsync_mode == TSYNC_MODE_PCRMASTER && !strcmp(tsync_mode_str, "pcrmaster")) {
1103 *tsync_mode = TSYNC_MODE_PCRMASTER;
1104 }
1105
1106 return *tsync_mode;
1107}
1108