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
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, ¶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 */
|