You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

237 lines
7.3 KiB

/*
* 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, &param->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 */