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 | |
32 | int adec_pts_droppcm(aml_audio_dec_t *audec); |
33 | int vdec_pts_resume(void); |
34 | static int vdec_pts_pause(void); |
35 | int droppcm_use_size(aml_audio_dec_t *audec, int drop_size); |
36 | void droppcm_prop_ctrl(int *audio_ahead, int *pts_ahead_val); |
37 | int droppcm_get_refpts(aml_audio_dec_t *audec, unsigned long *refpts); |
38 | |
39 | extern int match_types(const char *filetypestr, const char *typesetting); |
40 | |
41 | static 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 | |
48 | int 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 | /* |
64 | get vpts when refresh apts, do not use sys write servie as it is too slow sometimes. |
65 | */ |
66 | static 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 | |
88 | static 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 | |
104 | static 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 | */ |
114 | unsigned 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 | */ |
156 | int 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 | |
250 | static 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 | |
259 | int 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 | */ |
467 | int 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 | */ |
477 | int 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 | */ |
489 | static int apts_interrupt = 0; |
490 | static int pcrmaster_droppcm_flag = 0; |
491 | static int pre_filltime = -1; |
492 | int 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 | */ |
775 | int 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 | */ |
790 | int 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 | } |
822 | static int vdec_pts_pause(void) |
823 | { |
824 | char *path = "/sys/class/video_pause"; |
825 | return amsysfs_set_sysfs_int(path, 1); |
826 | |
827 | } |
828 | int 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) |
835 | int 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 | |
927 | void 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 | |
948 | int 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 | |
1083 | int 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 |