/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2019. All rights reserved. * Description: adec pts function * Author: audio * Create: 2019-12-30 */ #include "adec_pts.h" #include "mpi_adec_debug.h" #include "adec_fault_check.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ td_bool adec_is_pts_full(adec_pts_que *pts_que) { td_u32 pts_free = adec_buf_free_size(pts_que->pts_write, pts_que->pts_read, ADEC_MAX_STORED_PTS_NUM); return (pts_free <= 1); } static td_u32 adec_traverse_pts_array(adec_pts_que *pts_que, td_u32 read_pos, td_u32 *found_pos, td_bool *pos_matched) { td_u32 pos; td_u32 found_pts = ADEC_INVALID_PTS; adec_pts *pts_arry = pts_que->pts_arry; td_bool read_pos_flag = TD_FALSE; for (pos = pts_que->pts_read; pos != pts_que->pts_write; pos = (pos + 1) % ADEC_MAX_STORED_PTS_NUM) { if (pts_arry[pos].beg_pos < pts_arry[pos].end_pos) { if ((pts_arry[pos].beg_pos <= read_pos) && (pts_arry[pos].end_pos > read_pos)) { read_pos_flag = TD_TRUE; break; } } else { if ((pts_arry[pos].beg_pos <= read_pos) || (pts_arry[pos].end_pos > read_pos)) { read_pos_flag = TD_TRUE; break; } } } if (read_pos_flag == TD_TRUE) { found_pts = pts_arry[pos].pts; if (read_pos == pts_arry[pos].beg_pos) { *pos_matched = TD_TRUE; } } *found_pos = pos; return found_pts; } td_u32 adec_find_pts(adec_pts_find_info *param) { td_u32 pos; td_u32 pts = ADEC_INVALID_PTS; td_u32 found_pts = ADEC_INVALID_PTS; td_u32 read_pos; td_u32 frame_time; adec_pts_que *pts_que = TD_NULL; adec_pts *pts_arry = TD_NULL; if (param == TD_NULL) { return 0; } read_pos = param->read_pos; frame_time = param->frame_time; pts_que = param->pts_que; if (pts_que == TD_NULL) { soc_log_err("pts_que is null!\n"); return 0; } pts_arry = pts_que->pts_arry; param->out_pos_matched = TD_FALSE; param->out_pts_interpolated = TD_FALSE; param->out_org_pts = ADEC_INVALID_PTS; found_pts = adec_traverse_pts_array(pts_que, read_pos, &pos, ¶m->out_pos_matched); /* WARN: record first then pts_arry[pos].pts = ADEC_INVALID_PTS */ if (pos != pts_que->pts_write) { adec_record_pts_processed(pts_que, pos, 1); /* read 1 pts && discard other */ } if (found_pts == ADEC_INVALID_PTS) { /* can not find a valid PTS */ param->out_org_pts = ADEC_INVALID_PTS; if (pts_que->last_pts_ms != ADEC_INVALID_PTS) { pts = pts_que->last_pts_ms + frame_time; if (pts == ADEC_INVALID_PTS) { pts = 0; /* avoid loop */ } pts_que->last_pts_ms = pts; param->out_pts_interpolated = TD_TRUE; } pts_que->dfx.missed_pts_cnt++; } else { /* found a valid PTS */ pts = found_pts; pts_arry[pos].pts = ADEC_INVALID_PTS; param->out_org_pts = found_pts; pts_que->last_pts_ms = pts; } if (pos != pts_que->pts_write) { pts_que->pts_read = pos; } return pts; } td_u32 adec_find_fix_pts(adec_pts_que *pts_que, td_u32 end_pos, td_u32 frame_time, td_u32 *org_pts) { td_u32 pos; td_u32 pts = ADEC_INVALID_PTS; td_u32 found_pts_pos = ADEC_INVALID_PTS; adec_pts *pts_arry = pts_que->pts_arry; for (pos = pts_que->pts_read; pos != pts_que->pts_write; pos = (pos + 1) % ADEC_MAX_STORED_PTS_NUM) { if (pts_arry[pos].beg_pos < pts_arry[pos].end_pos) { if ((pts_arry[pos].beg_pos <= end_pos) && (pts_arry[pos].end_pos > end_pos)) { found_pts_pos = pts_arry[pos].pts; break; } } else { if ((pts_arry[pos].beg_pos <= end_pos) || (pts_arry[pos].end_pos > end_pos)) { found_pts_pos = pts_arry[pos].pts; break; } } } if (found_pts_pos == ADEC_INVALID_PTS) { /* can not find a valid PTS */ if (pts_que->last_pts_ms != ADEC_INVALID_PTS) { pts = pts_que->last_pts_ms + frame_time; if (pts == ADEC_INVALID_PTS) { pts = 0; /* avoid loop */ } pts_que->last_pts_ms = pts; } pts_que->dfx.missed_pts_cnt++; *org_pts = ADEC_INVALID_PTS; } else { /* found a valid PTS */ adec_record_pts_processed(pts_que, pos, 1); /* read 1 pts && discard other */ pts = found_pts_pos; pts_arry[pos].pts = ADEC_INVALID_PTS; pts_que->pts_read = pos; pts_que->last_pts_ms = pts; *org_pts = found_pts_pos; } return pts; } td_void adec_discard_pts(adec_pts_que *pts_que, td_u32 read_pos) { td_u32 pos; adec_pts *pts_arry = pts_que->pts_arry; for (pos = pts_que->pts_read; pos != pts_que->pts_write; pos = (pos + 1) % ADEC_MAX_STORED_PTS_NUM) { if (pts_arry[pos].beg_pos < pts_arry[pos].end_pos) { if ((pts_arry[pos].beg_pos <= read_pos) && (pts_arry[pos].end_pos > read_pos)) { break; } } else { if ((pts_arry[pos].beg_pos <= read_pos) || (pts_arry[pos].end_pos > read_pos)) { break; } } } adec_record_pts_processed(pts_que, pos, 0); pts_que->pts_read = pos; } td_void adec_store_pts(adec_pts_que *pts_que, const adec_chan_input_buf *in_buf, td_u32 pts, td_u32 size) { adec_pts *pts_arry = pts_que->pts_arry; td_u32 tmp_pts = pts; if (tmp_pts != ADEC_INVALID_PTS) { if (tmp_pts == pts_que->last_store_pts_ms) { tmp_pts = ADEC_INVALID_PTS; } } if (tmp_pts == ADEC_INVALID_PTS) { td_u32 pts_pos = ADEC_MAX_STORED_PTS_NUM - 1; if (pts_que->pts_write != 0) { pts_pos = pts_que->pts_write - 1; } pts_arry[pts_pos].end_pos = adec_sat_add(pts_arry[pts_pos].end_pos, size, in_buf->boundary); return; } if (pts_que->dfx.first_valid_pts == ADEC_INVALID_PTS) { pts_que->dfx.first_valid_pts = tmp_pts; } /* make sure there are space to store */ if (adec_is_pts_full(pts_que) == TD_TRUE) { pts_que->dfx.discard_pts_cnt++; soc_log_warn("not enough PTS buffer, discard current PTS(%d)\n", tmp_pts); return; } if (tmp_pts < pts_que->last_store_pts_ms) { if (pts_que->last_store_pts_ms == ADEC_INVALID_PTS) { pts_que->recyle_store_pts_ms = tmp_pts; /* first pts */ } else { pts_que->recyle_store_pts_ms = pts_que->last_store_pts_ms; /* pts re-cycle */ } pts_que->recycle_first_pts_ms = tmp_pts; } pts_que->last_store_pts_ms = tmp_pts; pts_arry[pts_que->pts_write].pts = tmp_pts; pts_arry[pts_que->pts_write].beg_pos = in_buf->stream_write_pos; pts_arry[pts_que->pts_write].end_pos = adec_sat_add(in_buf->stream_write_pos, size, in_buf->boundary); pts_que->pts_write = adec_sat_add(pts_que->pts_write, 1, ADEC_MAX_STORED_PTS_NUM); } #ifdef __cplusplus } #endif /* __cplusplus */