MLK-24960: [8QM_MEK/8QXP_MEK]mxc:vpu_malone: move timestamp manager to
firmware move timestamp to firmware, it will make our driver more easy to upstream Signed-off-by: Ming Qian <ming.qian@nxp.com>
This commit is contained in:
parent
bf67b06529
commit
21929af532
|
@ -11,7 +11,6 @@ vpu-malone-objs = vpu_b0.o \
|
||||||
vpu_rpc.o \
|
vpu_rpc.o \
|
||||||
insert_startcode.o \
|
insert_startcode.o \
|
||||||
vpu_debug_log.o \
|
vpu_debug_log.o \
|
||||||
vpu_ts.o \
|
|
||||||
vpu_mu.o \
|
vpu_mu.o \
|
||||||
vpu_pm.o
|
vpu_pm.o
|
||||||
|
|
||||||
|
|
|
@ -174,6 +174,7 @@ typedef enum {
|
||||||
VID_API_CMD_DBG_DUMP_LOG = 0x1F,
|
VID_API_CMD_DBG_DUMP_LOG = 0x1F,
|
||||||
/* Begin Encode CMDs */
|
/* Begin Encode CMDs */
|
||||||
VID_API_CMD_YUV_READY = 0x20,
|
VID_API_CMD_YUV_READY = 0x20,
|
||||||
|
VID_API_CMD_TS = 0x21,
|
||||||
|
|
||||||
VID_API_CMD_FIRM_RESET = 0x40,
|
VID_API_CMD_FIRM_RESET = 0x40,
|
||||||
|
|
||||||
|
@ -684,8 +685,13 @@ typedef struct {
|
||||||
u_int32 uFWOffset;
|
u_int32 uFWOffset;
|
||||||
u_int32 uMaxDecoderStreams;
|
u_int32 uMaxDecoderStreams;
|
||||||
MediaIPFW_Video_DbgLogDesc DbgLogDesc;
|
MediaIPFW_Video_DbgLogDesc DbgLogDesc;
|
||||||
MediaIPFW_Video_FrameBuffer StreamFrameBuffer[VID_API_NUM_STREAMS];
|
union {
|
||||||
MediaIPFW_Video_FrameBuffer StreamDCPBuffer[VID_API_NUM_STREAMS];
|
struct {
|
||||||
|
MediaIPFW_Video_FrameBuffer StreamFrameBuffer[VID_API_NUM_STREAMS];
|
||||||
|
MediaIPFW_Video_FrameBuffer StreamDCPBuffer[VID_API_NUM_STREAMS];
|
||||||
|
};
|
||||||
|
BUFFER_DESCRIPTOR_TYPE StreamApiCmdBufferDesc[VID_API_NUM_STREAMS];
|
||||||
|
};
|
||||||
MediaIPFW_Video_UData UDataBuffer[VID_API_NUM_STREAMS];
|
MediaIPFW_Video_UData UDataBuffer[VID_API_NUM_STREAMS];
|
||||||
MediaIPFW_Video_BufDesc DebugBufferDesc;
|
MediaIPFW_Video_BufDesc DebugBufferDesc;
|
||||||
MediaIPFW_Video_BufDesc EngAccessBufferDesc[VID_API_NUM_STREAMS];
|
MediaIPFW_Video_BufDesc EngAccessBufferDesc[VID_API_NUM_STREAMS];
|
||||||
|
|
|
@ -45,12 +45,18 @@
|
||||||
#include "vpu_b0.h"
|
#include "vpu_b0.h"
|
||||||
#include "insert_startcode.h"
|
#include "insert_startcode.h"
|
||||||
#include "vpu_debug_log.h"
|
#include "vpu_debug_log.h"
|
||||||
#include "vpu_ts.h"
|
|
||||||
#include "vpu_pm.h"
|
#include "vpu_pm.h"
|
||||||
#include "vpu_mu.h"
|
#include "vpu_mu.h"
|
||||||
|
|
||||||
|
#ifndef TSM_TIMESTAMP_NONE
|
||||||
|
#define TSM_TIMESTAMP_NONE -1L
|
||||||
|
#endif
|
||||||
|
#ifndef TSM_TS_IS_VALID
|
||||||
|
#define TSM_TS_IS_VALID(ts) ((ts) >= 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned int vpu_dbg_level_decoder = LVL_WARN;
|
unsigned int vpu_dbg_level_decoder = LVL_WARN;
|
||||||
static int vpu_frm_depth = INVALID_FRAME_DEPTH;
|
static int vpu_frm_depth = VPU_FRAME_DEPTH_DEFAULT;
|
||||||
static int vpu_log_depth = DEFAULT_LOG_DEPTH;
|
static int vpu_log_depth = DEFAULT_LOG_DEPTH;
|
||||||
static int vpu_max_bufsize = MAX_BUFFER_SIZE;
|
static int vpu_max_bufsize = MAX_BUFFER_SIZE;
|
||||||
static int vpu_frmdbg_ena = DEFAULT_FRMDBG_ENABLE;
|
static int vpu_frmdbg_ena = DEFAULT_FRMDBG_ENABLE;
|
||||||
|
@ -59,9 +65,6 @@ static int vpu_frmdbg_raw = 1;
|
||||||
static int vpu_dbe_num = 1;
|
static int vpu_dbe_num = 1;
|
||||||
static int vpu_frmcrcdump_ena;
|
static int vpu_frmcrcdump_ena;
|
||||||
static int stream_buffer_threshold = 0x10000;
|
static int stream_buffer_threshold = 0x10000;
|
||||||
static int tsm_mode = MODE_AI;
|
|
||||||
static int tsm_buffer_size = 1024;
|
|
||||||
static int tsm_use_consumed_length = 1;
|
|
||||||
static int precheck_show_bytes;
|
static int precheck_show_bytes;
|
||||||
static int vpu_show_perf_ena;
|
static int vpu_show_perf_ena;
|
||||||
static int vpu_show_perf_idx = (1 << VPU_MAX_NUM_STREAMS) - 1;
|
static int vpu_show_perf_idx = (1 << VPU_MAX_NUM_STREAMS) - 1;
|
||||||
|
@ -133,6 +136,7 @@ static char *cmd2str[] = {
|
||||||
"VID_API_CMD_DBG_STOP_LOG",
|
"VID_API_CMD_DBG_STOP_LOG",
|
||||||
"VID_API_CMD_DBG_DUMP_LOG",
|
"VID_API_CMD_DBG_DUMP_LOG",
|
||||||
"VID_API_CMD_YUV_READY", /*0x20*/
|
"VID_API_CMD_YUV_READY", /*0x20*/
|
||||||
|
"VID_API_CMD_TS",
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *event2str[] = {
|
static char *event2str[] = {
|
||||||
|
@ -279,7 +283,7 @@ static void count_cmd(struct vpu_statistic *statistic, u32 cmdid)
|
||||||
if (cmdid < ARRAY_SIZE(cmd2str))
|
if (cmdid < ARRAY_SIZE(cmd2str))
|
||||||
statistic->cmd[cmdid]++;
|
statistic->cmd[cmdid]++;
|
||||||
else
|
else
|
||||||
statistic->cmd[VID_API_CMD_YUV_READY + 1]++;
|
statistic->cmd[VID_API_CMD_TS + 1]++;
|
||||||
statistic->current_cmd = cmdid;
|
statistic->current_cmd = cmdid;
|
||||||
ktime_get_raw_ts64(&statistic->ts_cmd);
|
ktime_get_raw_ts64(&statistic->ts_cmd);
|
||||||
}
|
}
|
||||||
|
@ -1528,7 +1532,8 @@ static void vpu_dec_receive_ts(struct vpu_ctx *ctx,
|
||||||
int size)
|
int size)
|
||||||
{
|
{
|
||||||
struct vb2_v4l2_buffer *vbuf;
|
struct vb2_v4l2_buffer *vbuf;
|
||||||
TSM_TIMESTAMP input_ts;
|
s64 input_ts;
|
||||||
|
u32 data[3];
|
||||||
|
|
||||||
if (!ctx || !vb)
|
if (!ctx || !vb)
|
||||||
return;
|
return;
|
||||||
|
@ -1548,31 +1553,25 @@ static void vpu_dec_receive_ts(struct vpu_ctx *ctx,
|
||||||
if (TSM_TS_IS_VALID(input_ts) && input_ts > ctx->output_ts)
|
if (TSM_TS_IS_VALID(input_ts) && input_ts > ctx->output_ts)
|
||||||
ctx->output_ts = input_ts;
|
ctx->output_ts = input_ts;
|
||||||
|
|
||||||
if (down_interruptible(&ctx->tsm_lock)) {
|
|
||||||
vpu_err("%s() get tsm lock fail\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_codec_config_data(vb) && !TSM_TS_IS_VALID(input_ts)) {
|
if (is_codec_config_data(vb) && !TSM_TS_IS_VALID(input_ts)) {
|
||||||
vpu_dbg(LVL_BIT_TS, "[INPUT TS]codec data\n");
|
vpu_dbg(LVL_BIT_TS, "[INPUT TS]codec data\n");
|
||||||
ctx->extra_size += size;
|
ctx->extra_size += size;
|
||||||
up(&ctx->tsm_lock);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->tsm_sync_flag) {
|
|
||||||
vpu_dbg(LVL_BIT_TS, "resyncTSManager\n");
|
|
||||||
resyncTSManager(ctx->tsm, input_ts, tsm_mode);
|
|
||||||
ctx->tsm_sync_flag = false;
|
|
||||||
}
|
|
||||||
size += ctx->extra_size;
|
size += ctx->extra_size;
|
||||||
ctx->extra_size = 0;
|
ctx->extra_size = 0;
|
||||||
vpu_dbg(LVL_BIT_TS, "[INPUT TS]%32lld\n", input_ts);
|
vpu_dbg(LVL_BIT_TS, "[INPUT TS]%32lld\n", input_ts);
|
||||||
TSManagerReceive2(ctx->tsm, input_ts, size);
|
|
||||||
ctx->total_ts_bytes += size;
|
if (input_ts < 0) {
|
||||||
vpu_dbg(LVL_BIT_FRAME_BYTES, "[%d]receive bytes : %8d / %16ld\n",
|
data[0] = (u32)-1;
|
||||||
ctx->str_index, size, ctx->total_ts_bytes);
|
data[1] = 0;
|
||||||
up(&ctx->tsm_lock);
|
} else {
|
||||||
|
data[0] = input_ts / NSEC_PER_SEC;
|
||||||
|
data[1] = input_ts % NSEC_PER_SEC;
|
||||||
|
}
|
||||||
|
data[2] = size;
|
||||||
|
v4l2_vpu_send_cmd(ctx, ctx->str_index, VID_API_CMD_TS, 3, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int v4l2_ioctl_qbuf(struct file *file,
|
static int v4l2_ioctl_qbuf(struct file *file,
|
||||||
|
@ -1618,74 +1617,6 @@ static int v4l2_ioctl_qbuf(struct file *file,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vpu_dec_send_ts(struct vpu_ctx *ctx, struct v4l2_buffer *buf)
|
|
||||||
{
|
|
||||||
TSM_TIMESTAMP ts;
|
|
||||||
struct timespec64 ts64;
|
|
||||||
|
|
||||||
if (down_interruptible(&ctx->tsm_lock)) {
|
|
||||||
vpu_err("%s() get tsm lock fail\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ts = TSManagerSend2(ctx->tsm, NULL);
|
|
||||||
if (TSM_TS_IS_VALID(ts) && ts < ctx->capture_ts) {
|
|
||||||
vpu_dbg(LVL_BIT_TS, "revise timestamp: %32lld -> %32lld\n",
|
|
||||||
ts, ctx->capture_ts);
|
|
||||||
ts = ctx->capture_ts;
|
|
||||||
}
|
|
||||||
vpu_dbg(LVL_BIT_TS, "[OUTPUT TS]%32lld (%lld)\n",
|
|
||||||
ts, getTSManagerFrameInterval(ctx->tsm));
|
|
||||||
ts64 = ns_to_timespec64(ts);
|
|
||||||
buf->timestamp.tv_sec = ts64.tv_sec;
|
|
||||||
buf->timestamp.tv_usec = ts64.tv_nsec / NSEC_PER_USEC;
|
|
||||||
buf->flags |= V4L2_BUF_FLAG_TIMESTAMP_COPY;
|
|
||||||
|
|
||||||
up(&ctx->tsm_lock);
|
|
||||||
|
|
||||||
if (TSM_TS_IS_VALID(ts))
|
|
||||||
ctx->capture_ts = ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vpu_dec_valid_ts(struct vpu_ctx *ctx,
|
|
||||||
u32 consumed_pic_bytesused,
|
|
||||||
struct vb2_data_req *p_data_req)
|
|
||||||
{
|
|
||||||
WARN_ON(!ctx || !ctx->tsm);
|
|
||||||
|
|
||||||
if (down_interruptible(&ctx->tsm_lock)) {
|
|
||||||
vpu_err("%s() get tsm lock fail\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vpu_dbg(LVL_BIT_FRAME_BYTES, "[%d]Valid bytes : %8d / %16ld\n",
|
|
||||||
ctx->str_index, consumed_pic_bytesused,
|
|
||||||
ctx->total_consumed_bytes);
|
|
||||||
TSManagerValid2(ctx->tsm,
|
|
||||||
consumed_pic_bytesused,
|
|
||||||
p_data_req ? p_data_req->vb2_buf : NULL);
|
|
||||||
|
|
||||||
up(&ctx->tsm_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vpu_dec_skip_ts(struct vpu_ctx *ctx)
|
|
||||||
{
|
|
||||||
TSM_TIMESTAMP ts;
|
|
||||||
|
|
||||||
WARN_ON(!ctx || !ctx->tsm);
|
|
||||||
|
|
||||||
if (down_interruptible(&ctx->tsm_lock)) {
|
|
||||||
vpu_err("%s() get tsm lock fail\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ts = TSManagerSend2(ctx->tsm, NULL);
|
|
||||||
|
|
||||||
up(&ctx->tsm_lock);
|
|
||||||
|
|
||||||
vpu_dbg(LVL_BIT_TS, "[SKIP TS]%32lld\n", ts);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int v4l2_ioctl_dqbuf(struct file *file,
|
static int v4l2_ioctl_dqbuf(struct file *file,
|
||||||
void *fh,
|
void *fh,
|
||||||
struct v4l2_buffer *buf
|
struct v4l2_buffer *buf
|
||||||
|
@ -1719,8 +1650,6 @@ static int v4l2_ioctl_dqbuf(struct file *file,
|
||||||
if (!V4L2_TYPE_IS_OUTPUT(buf->type) && is_10bit_format(ctx))
|
if (!V4L2_TYPE_IS_OUTPUT(buf->type) && is_10bit_format(ctx))
|
||||||
buf->reserved = 1;
|
buf->reserved = 1;
|
||||||
|
|
||||||
if (!V4L2_TYPE_IS_OUTPUT(buf->type))
|
|
||||||
vpu_dec_send_ts(ctx, buf);
|
|
||||||
if (V4L2_TYPE_IS_OUTPUT(buf->type))
|
if (V4L2_TYPE_IS_OUTPUT(buf->type))
|
||||||
buf->flags &= ~V4L2_NXP_BUF_MASK_FLAGS;
|
buf->flags &= ~V4L2_NXP_BUF_MASK_FLAGS;
|
||||||
|
|
||||||
|
@ -1967,32 +1896,6 @@ static int vpu_dec_v4l2_ioctl_g_parm(struct file *file, void *fh,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vpu_dec_set_tsm_frame_rate(struct vpu_ctx *ctx)
|
|
||||||
{
|
|
||||||
u32 numerator;
|
|
||||||
u32 denominator;
|
|
||||||
|
|
||||||
WARN_ON(!ctx || !ctx->tsm);
|
|
||||||
|
|
||||||
if (down_interruptible(&ctx->tsm_lock)) {
|
|
||||||
vpu_err("%s() get tsm lock fail\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
numerator = ctx->fixed_frame_interval.numerator;
|
|
||||||
denominator = ctx->fixed_frame_interval.denominator;
|
|
||||||
if (numerator && denominator) {
|
|
||||||
setTSManagerFrameRate(ctx->tsm, denominator, numerator);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
numerator = ctx->frame_interval.numerator;
|
|
||||||
denominator = ctx->frame_interval.denominator;
|
|
||||||
if (numerator && denominator)
|
|
||||||
setTSManagerFrameRate(ctx->tsm, denominator, numerator);
|
|
||||||
exit:
|
|
||||||
up(&ctx->tsm_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vpu_dec_v4l2_ioctl_s_parm(struct file *file, void *fh,
|
static int vpu_dec_v4l2_ioctl_s_parm(struct file *file, void *fh,
|
||||||
struct v4l2_streamparm *parm)
|
struct v4l2_streamparm *parm)
|
||||||
{
|
{
|
||||||
|
@ -2012,7 +1915,6 @@ static int vpu_dec_v4l2_ioctl_s_parm(struct file *file, void *fh,
|
||||||
parm->parm.capture.timeperframe.numerator / gcd;
|
parm->parm.capture.timeperframe.numerator / gcd;
|
||||||
ctx->fixed_frame_interval.denominator =
|
ctx->fixed_frame_interval.denominator =
|
||||||
parm->parm.capture.timeperframe.denominator / gcd;
|
parm->parm.capture.timeperframe.denominator / gcd;
|
||||||
vpu_dec_set_tsm_frame_rate(ctx);
|
|
||||||
mutex_unlock(&ctx->instance_mutex);
|
mutex_unlock(&ctx->instance_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2128,8 +2030,8 @@ static struct v4l2_ctrl_config vpu_custom_s_cfg[] = {
|
||||||
.id = V4L2_CID_USER_FRAME_DEPTH,
|
.id = V4L2_CID_USER_FRAME_DEPTH,
|
||||||
.name = "frame depth ctrl",
|
.name = "frame depth ctrl",
|
||||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||||
.min = -1,
|
.min = 1,
|
||||||
.max = 999,
|
.max = VPU_FRAME_DEPTH_MAX,
|
||||||
.step = 1,
|
.step = 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2497,6 +2399,8 @@ static void update_wptr(struct vpu_ctx *ctx,
|
||||||
length = (wptr + size - pStrBufDesc->wptr) % size;
|
length = (wptr + size - pStrBufDesc->wptr) % size;
|
||||||
ctx->total_write_bytes += length;
|
ctx->total_write_bytes += length;
|
||||||
|
|
||||||
|
vpu_dbg(LVL_BIT_FRAME_BYTES, "[%d]receive bytes : %8d / %16ld\n",
|
||||||
|
ctx->str_index, length, ctx->total_write_bytes);
|
||||||
vpu_dbg(LVL_BIT_WPTR, "ctx[%d] wptr : 0x%08x -> 0x%08x\n",
|
vpu_dbg(LVL_BIT_WPTR, "ctx[%d] wptr : 0x%08x -> 0x%08x\n",
|
||||||
ctx->str_index, pStrBufDesc->wptr, wptr);
|
ctx->str_index, pStrBufDesc->wptr, wptr);
|
||||||
pStrBufDesc->wptr = wptr;
|
pStrBufDesc->wptr = wptr;
|
||||||
|
@ -2776,6 +2680,8 @@ static void vpu_dec_send_cmd(struct vpu_dev *dev, u32 idx, u32 cmdid,
|
||||||
{
|
{
|
||||||
WARN_ON(!dev || idx >= VPU_MAX_NUM_STREAMS);
|
WARN_ON(!dev || idx >= VPU_MAX_NUM_STREAMS);
|
||||||
|
|
||||||
|
if (!rpc_check_is_ready(&dev->shared_mem, idx))
|
||||||
|
vpu_err("[%d] is not ready\n", idx);
|
||||||
mutex_lock(&dev->cmd_mutex);
|
mutex_lock(&dev->cmd_mutex);
|
||||||
rpc_send_cmd_buf(&dev->shared_mem, idx, cmdid, cmdnum, local_cmddata);
|
rpc_send_cmd_buf(&dev->shared_mem, idx, cmdid, cmdnum, local_cmddata);
|
||||||
mb();
|
mb();
|
||||||
|
@ -3014,7 +2920,6 @@ static int send_start_cmd(struct vpu_ctx *ctx)
|
||||||
pStrBufDesc->start = ctx->stream_buffer.dma_phy;
|
pStrBufDesc->start = ctx->stream_buffer.dma_phy;
|
||||||
pStrBufDesc->end = ctx->stream_buffer.dma_phy + ctx->stream_buffer.dma_size;
|
pStrBufDesc->end = ctx->stream_buffer.dma_phy + ctx->stream_buffer.dma_size;
|
||||||
pStrBufDesc->LWM = 0x01;
|
pStrBufDesc->LWM = 0x01;
|
||||||
ctx->pre_pic_end_addr = pStrBufDesc->start;
|
|
||||||
ctx->beginning = pStrBufDesc->start;
|
ctx->beginning = pStrBufDesc->start;
|
||||||
|
|
||||||
pSharedInterface->pStreamBuffDesc[ctx->str_index][uStrBufIdx] =
|
pSharedInterface->pStreamBuffDesc[ctx->str_index][uStrBufIdx] =
|
||||||
|
@ -3046,7 +2951,6 @@ static int send_start_cmd(struct vpu_ctx *ctx)
|
||||||
|
|
||||||
v4l2_vpu_send_cmd(ctx, ctx->str_index, VID_API_CMD_START, 0, NULL);
|
v4l2_vpu_send_cmd(ctx, ctx->str_index, VID_API_CMD_START, 0, NULL);
|
||||||
ctx->firmware_stopped = false;
|
ctx->firmware_stopped = false;
|
||||||
ctx->tsm_sync_flag = true;
|
|
||||||
ctx->first_data_flag = true;
|
ctx->first_data_flag = true;
|
||||||
|
|
||||||
vpu_calculate_performance(ctx, 0xff, "send start cmd");
|
vpu_calculate_performance(ctx, 0xff, "send start cmd");
|
||||||
|
@ -3358,8 +3262,6 @@ static void fill_stream_buffer_info(struct vpu_ctx *ctx)
|
||||||
buffer_info->stream_buffer_threshold = frame_threshold[idx];
|
buffer_info->stream_buffer_threshold = frame_threshold[idx];
|
||||||
else
|
else
|
||||||
buffer_info->stream_buffer_threshold = 0;
|
buffer_info->stream_buffer_threshold = 0;
|
||||||
|
|
||||||
buffer_info->stream_pic_input_count = ctx->frm_total_num;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_pic_end_flag(struct vpu_ctx *ctx)
|
static void set_pic_end_flag(struct vpu_ctx *ctx)
|
||||||
|
@ -3386,9 +3288,6 @@ static bool vpu_dec_stream_is_ready(struct vpu_ctx *ctx)
|
||||||
if (ctx->fifo_low)
|
if (ctx->fifo_low)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (ctx->tsm_sync_flag)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
pStrBufDesc = get_str_buffer_desc(ctx);
|
pStrBufDesc = get_str_buffer_desc(ctx);
|
||||||
stream_size = got_used_space(pStrBufDesc->wptr,
|
stream_size = got_used_space(pStrBufDesc->wptr,
|
||||||
pStrBufDesc->rptr,
|
pStrBufDesc->rptr,
|
||||||
|
@ -3402,15 +3301,11 @@ static bool vpu_dec_stream_is_ready(struct vpu_ctx *ctx)
|
||||||
/*
|
/*
|
||||||
*frame depth need to be set by user and then the condition works
|
*frame depth need to be set by user and then the condition works
|
||||||
*/
|
*/
|
||||||
if (vpu_frm_depth != INVALID_FRAME_DEPTH &&
|
if (vpu_frm_depth > 0 && ctx->stream_input_mode == FRAME_LVL) {
|
||||||
ctx->stream_input_mode == FRAME_LVL) {
|
if (ctx->frm_dec_delay >= vpu_frm_depth)
|
||||||
if ((getTSManagerPreBufferCnt(ctx->tsm)) >= vpu_frm_depth)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((getTSManagerPreBufferCnt(ctx->tsm)) >= (tsm_buffer_size * 9 / 10))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (ctx->ts_threshold > 0 &&
|
if (ctx->ts_threshold > 0 &&
|
||||||
TSM_TS_IS_VALID(ctx->output_ts) &&
|
TSM_TS_IS_VALID(ctx->output_ts) &&
|
||||||
TSM_TS_IS_VALID(ctx->capture_ts)) {
|
TSM_TS_IS_VALID(ctx->capture_ts)) {
|
||||||
|
@ -3569,11 +3464,14 @@ static void report_buffer_done(struct vpu_ctx *ctx, void *frame_info)
|
||||||
u_int32 *FrameInfo = (u_int32 *)frame_info;
|
u_int32 *FrameInfo = (u_int32 *)frame_info;
|
||||||
u_int32 fs_id = FrameInfo[0x0];
|
u_int32 fs_id = FrameInfo[0x0];
|
||||||
uint32_t stride = FrameInfo[3];
|
uint32_t stride = FrameInfo[3];
|
||||||
|
s64 timestamp = ((s32)FrameInfo[9] * NSEC_PER_SEC) + FrameInfo[10];
|
||||||
bool b10BitFormat = is_10bit_format(ctx);
|
bool b10BitFormat = is_10bit_format(ctx);
|
||||||
int buffer_id;
|
int buffer_id;
|
||||||
|
|
||||||
vpu_dbg(LVL_BIT_FUNC, "%s() fs_id=%d, ulFsLumaBase[0]=%x, stride=%d, b10BitFormat=%d, ctx->seqinfo.uBitDepthLuma=%d\n",
|
vpu_dbg(LVL_BIT_FUNC, "%s() fs_id=%d, ulFsLumaBase[0]=%x, stride=%d, b10BitFormat=%d, ctx->seqinfo.uBitDepthLuma=%d\n",
|
||||||
__func__, fs_id, FrameInfo[1], stride, b10BitFormat, ctx->seqinfo.uBitDepthLuma);
|
__func__, fs_id, FrameInfo[1], stride, b10BitFormat, ctx->seqinfo.uBitDepthLuma);
|
||||||
|
vpu_dbg(LVL_BIT_TS, "[OUTPUT TS]%32lld\n", timestamp);
|
||||||
|
ctx->capture_ts = timestamp;
|
||||||
v4l2_update_stream_addr(ctx, 0);
|
v4l2_update_stream_addr(ctx, 0);
|
||||||
|
|
||||||
buffer_id = find_buffer_id(ctx, FrameInfo[1]);
|
buffer_id = find_buffer_id(ctx, FrameInfo[1]);
|
||||||
|
@ -3590,7 +3488,6 @@ static void report_buffer_done(struct vpu_ctx *ctx, void *frame_info)
|
||||||
set_data_req_status(p_data_req, FRAME_SKIP);
|
set_data_req_status(p_data_req, FRAME_SKIP);
|
||||||
up(&This->drv_q_lock);
|
up(&This->drv_q_lock);
|
||||||
|
|
||||||
vpu_dec_skip_ts(ctx);
|
|
||||||
send_skip_event(ctx);
|
send_skip_event(ctx);
|
||||||
ctx->frm_dis_delay--;
|
ctx->frm_dis_delay--;
|
||||||
return;
|
return;
|
||||||
|
@ -3613,6 +3510,7 @@ static void report_buffer_done(struct vpu_ctx *ctx, void *frame_info)
|
||||||
if (p_data_req->vb2_buf) {
|
if (p_data_req->vb2_buf) {
|
||||||
p_data_req->vb2_buf->planes[0].bytesused = This->sizeimage[0];
|
p_data_req->vb2_buf->planes[0].bytesused = This->sizeimage[0];
|
||||||
p_data_req->vb2_buf->planes[1].bytesused = This->sizeimage[1];
|
p_data_req->vb2_buf->planes[1].bytesused = This->sizeimage[1];
|
||||||
|
p_data_req->vb2_buf->timestamp = timestamp;
|
||||||
if (p_data_req->vb2_buf->state == VB2_BUF_STATE_ACTIVE)
|
if (p_data_req->vb2_buf->state == VB2_BUF_STATE_ACTIVE)
|
||||||
vb2_buffer_done(p_data_req->vb2_buf,
|
vb2_buffer_done(p_data_req->vb2_buf,
|
||||||
VB2_BUF_STATE_DONE);
|
VB2_BUF_STATE_DONE);
|
||||||
|
@ -3733,69 +3631,6 @@ static void add_buffer_to_queue(struct queue_data *q_data, struct vb2_data_req *
|
||||||
data_req->queued = true;
|
data_req->queued = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 correct_consumed_length(struct vpu_ctx *ctx,
|
|
||||||
u32 consumed_pic_bytesused)
|
|
||||||
{
|
|
||||||
long total_read_bytes;
|
|
||||||
long delta;
|
|
||||||
u32 circle_count;
|
|
||||||
u32 stream_size;
|
|
||||||
pSTREAM_BUFFER_DESCRIPTOR_TYPE pStrBufDesc;
|
|
||||||
|
|
||||||
pStrBufDesc = get_str_buffer_desc(ctx);
|
|
||||||
stream_size = got_used_space(pStrBufDesc->wptr,
|
|
||||||
pStrBufDesc->rptr,
|
|
||||||
pStrBufDesc->start,
|
|
||||||
pStrBufDesc->end);
|
|
||||||
total_read_bytes = ctx->total_write_bytes - stream_size;
|
|
||||||
delta = total_read_bytes - ctx->total_consumed_bytes;
|
|
||||||
if (delta < ctx->stream_buffer.dma_size)
|
|
||||||
return consumed_pic_bytesused;
|
|
||||||
|
|
||||||
circle_count = delta / ctx->stream_buffer.dma_size;
|
|
||||||
vpu_dbg(LVL_BIT_FRAME_BYTES,
|
|
||||||
"ctx[%d] cross over %d circles\n",
|
|
||||||
ctx->str_index, circle_count);
|
|
||||||
|
|
||||||
consumed_pic_bytesused += ctx->stream_buffer.dma_size * circle_count;
|
|
||||||
ctx->total_consumed_bytes += ctx->stream_buffer.dma_size * circle_count;
|
|
||||||
|
|
||||||
return consumed_pic_bytesused;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 get_consumed_pic_bytesused(struct vpu_ctx *ctx,
|
|
||||||
u32 pic_start_addr,
|
|
||||||
u32 pic_end_addr)
|
|
||||||
{
|
|
||||||
u32 consumed_pic_bytesused;
|
|
||||||
u32 pic_size;
|
|
||||||
|
|
||||||
consumed_pic_bytesused = pic_end_addr +
|
|
||||||
+ ctx->stream_buffer.dma_size
|
|
||||||
- ctx->pre_pic_end_addr;
|
|
||||||
consumed_pic_bytesused %= ctx->stream_buffer.dma_size;
|
|
||||||
pic_size = pic_end_addr + ctx->stream_buffer.dma_size - pic_start_addr;
|
|
||||||
pic_size %= ctx->stream_buffer.dma_size;
|
|
||||||
|
|
||||||
ctx->total_consumed_bytes += consumed_pic_bytesused;
|
|
||||||
consumed_pic_bytesused = correct_consumed_length(ctx,
|
|
||||||
consumed_pic_bytesused);
|
|
||||||
|
|
||||||
vpu_dbg(LVL_BIT_PIC_ADDR, "<0x%08x 0x%08x>, %8d, %8d\n",
|
|
||||||
pic_start_addr, pic_end_addr, pic_size, consumed_pic_bytesused);
|
|
||||||
if (consumed_pic_bytesused < pic_size)
|
|
||||||
vpu_err("ErrorAddr:[%d] Start(0x%x), End(0x%x), preEnd(0x%x)\n",
|
|
||||||
ctx->str_index,
|
|
||||||
pic_start_addr,
|
|
||||||
pic_end_addr,
|
|
||||||
ctx->pre_pic_end_addr);
|
|
||||||
|
|
||||||
|
|
||||||
ctx->pre_pic_end_addr = pic_end_addr;
|
|
||||||
|
|
||||||
return consumed_pic_bytesused;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_frame_interval_from_seqinfo(struct vpu_ctx *ctx,
|
static int parse_frame_interval_from_seqinfo(struct vpu_ctx *ctx,
|
||||||
MediaIPFW_Video_SeqInfo *seq_info)
|
MediaIPFW_Video_SeqInfo *seq_info)
|
||||||
{
|
{
|
||||||
|
@ -3814,10 +3649,6 @@ static int parse_frame_interval_from_seqinfo(struct vpu_ctx *ctx,
|
||||||
ctx->frame_interval.numerator /= gcd;
|
ctx->frame_interval.numerator /= gcd;
|
||||||
ctx->frame_interval.denominator /= gcd;
|
ctx->frame_interval.denominator /= gcd;
|
||||||
|
|
||||||
mutex_lock(&ctx->instance_mutex);
|
|
||||||
vpu_dec_set_tsm_frame_rate(ctx);
|
|
||||||
mutex_unlock(&ctx->instance_mutex);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4326,12 +4157,11 @@ static void vpu_api_event_handler(struct vpu_ctx *ctx, u_int32 uStrIdx, u_int32
|
||||||
int buffer_id;
|
int buffer_id;
|
||||||
u_int32 uDecFrmId = event_data[7];
|
u_int32 uDecFrmId = event_data[7];
|
||||||
u_int32 uPicStartAddr = event_data[10];
|
u_int32 uPicStartAddr = event_data[10];
|
||||||
u_int32 uPicEndAddr = event_data[12];
|
|
||||||
struct queue_data *This = &ctx->q_data[V4L2_DST];
|
struct queue_data *This = &ctx->q_data[V4L2_DST];
|
||||||
u_int32 uDpbmcCrc;
|
u_int32 uDpbmcCrc;
|
||||||
size_t wr_size;
|
size_t wr_size;
|
||||||
u32 consumed_pic_bytesused = 0;
|
|
||||||
struct vb2_data_req *p_data_req = NULL;
|
struct vb2_data_req *p_data_req = NULL;
|
||||||
|
u32 consumed_count = event_data[13];
|
||||||
|
|
||||||
if (This->vdec_std == VPU_VIDEO_HEVC)
|
if (This->vdec_std == VPU_VIDEO_HEVC)
|
||||||
uDpbmcCrc = pPerfDcpInfo->uDBEDpbCRC[0];
|
uDpbmcCrc = pPerfDcpInfo->uDBEDpbCRC[0];
|
||||||
|
@ -4351,20 +4181,10 @@ static void vpu_api_event_handler(struct vpu_ctx *ctx, u_int32 uStrIdx, u_int32
|
||||||
event_data[0], uPicStartAddr, pQMeterInfo, pPicInfo,
|
event_data[0], uPicStartAddr, pQMeterInfo, pPicInfo,
|
||||||
pDispInfo, pPerfInfo, pPerfDcpInfo);
|
pDispInfo, pPerfInfo, pPerfDcpInfo);
|
||||||
|
|
||||||
down(&ctx->q_data[V4L2_SRC].drv_q_lock);
|
|
||||||
if (tsm_use_consumed_length)
|
|
||||||
consumed_pic_bytesused = get_consumed_pic_bytesused(ctx,
|
|
||||||
uPicStartAddr,
|
|
||||||
uPicEndAddr);
|
|
||||||
up(&ctx->q_data[V4L2_SRC].drv_q_lock);
|
|
||||||
|
|
||||||
buffer_id = find_buffer_id(ctx, event_data[0]);
|
buffer_id = find_buffer_id(ctx, event_data[0]);
|
||||||
if (buffer_id == -1) {
|
if (buffer_id == -1) {
|
||||||
vpu_err("error: %s() ctx[%d] not find buffer id: %d, addr: 0x%x\n",
|
vpu_err("error: %s() ctx[%d] not find buffer id: %d, addr: 0x%x\n",
|
||||||
__func__, ctx->str_index, uDecFrmId, event_data[0]);
|
__func__, ctx->str_index, uDecFrmId, event_data[0]);
|
||||||
vpu_dec_valid_ts(ctx,
|
|
||||||
consumed_pic_bytesused,
|
|
||||||
NULL);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4375,18 +4195,20 @@ static void vpu_api_event_handler(struct vpu_ctx *ctx, u_int32 uStrIdx, u_int32
|
||||||
else
|
else
|
||||||
p_data_req->bfield = true;
|
p_data_req->bfield = true;
|
||||||
|
|
||||||
vpu_dec_valid_ts(ctx, consumed_pic_bytesused, p_data_req);
|
|
||||||
This->process_count++;
|
This->process_count++;
|
||||||
}
|
|
||||||
if (ctx->statistic.event[VID_API_EVENT_PIC_DECODED] == 1)
|
if (ctx->statistic.event[VID_API_EVENT_PIC_DECODED] == 1)
|
||||||
vpu_calculate_performance(ctx, uEvent, "first decoded");
|
vpu_calculate_performance(ctx, uEvent, "first decoded");
|
||||||
else
|
else
|
||||||
vpu_calculate_performance(ctx, uEvent, NULL);
|
vpu_calculate_performance(ctx, uEvent, NULL);
|
||||||
|
|
||||||
ctx->frm_dec_delay--;
|
if (ctx->frm_dec_delay >= consumed_count)
|
||||||
|
ctx->frm_dec_delay -= consumed_count;
|
||||||
|
else
|
||||||
|
ctx->frm_dec_delay = 0;
|
||||||
ctx->fifo_low = false;
|
ctx->fifo_low = false;
|
||||||
ctx->frame_decoded = true;
|
ctx->frame_decoded = true;
|
||||||
v4l2_update_stream_addr(ctx, 0);
|
v4l2_update_stream_addr(ctx, 0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case VID_API_EVENT_SEQ_HDR_FOUND: {
|
case VID_API_EVENT_SEQ_HDR_FOUND: {
|
||||||
MediaIPFW_Video_SeqInfo *pSeqInfo = (MediaIPFW_Video_SeqInfo *)dev->shared_mem.seq_mem_vir;
|
MediaIPFW_Video_SeqInfo *pSeqInfo = (MediaIPFW_Video_SeqInfo *)dev->shared_mem.seq_mem_vir;
|
||||||
|
@ -4522,10 +4344,8 @@ static void vpu_api_event_handler(struct vpu_ctx *ctx, u_int32 uStrIdx, u_int32
|
||||||
vpu_dbg(LVL_INFO, "warning: normal release and previous status %s, frame not for display, queue the buffer to list again\n",
|
vpu_dbg(LVL_INFO, "warning: normal release and previous status %s, frame not for display, queue the buffer to list again\n",
|
||||||
bufstat[p_data_req->status]);
|
bufstat[p_data_req->status]);
|
||||||
|
|
||||||
if (p_data_req->status == FRAME_DECODED) {
|
if (p_data_req->status == FRAME_DECODED)
|
||||||
vpu_dec_skip_ts(ctx);
|
|
||||||
send_skip_event(ctx);
|
send_skip_event(ctx);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (p_data_req->status != FRAME_ALLOC) {
|
if (p_data_req->status != FRAME_ALLOC) {
|
||||||
set_data_req_status(p_data_req, FRAME_RELEASE);
|
set_data_req_status(p_data_req, FRAME_RELEASE);
|
||||||
|
@ -4607,20 +4427,14 @@ static void vpu_api_event_handler(struct vpu_ctx *ctx, u_int32 uStrIdx, u_int32
|
||||||
queue->qbuf_count,
|
queue->qbuf_count,
|
||||||
queue->dqbuf_count);
|
queue->dqbuf_count);
|
||||||
vpu_dbg(LVL_BIT_FRAME_BYTES,
|
vpu_dbg(LVL_BIT_FRAME_BYTES,
|
||||||
"[%d]total bytes: %ld, %ld, %ld, %ld\n",
|
"[%d]total bytes: %ld, %ld\n",
|
||||||
ctx->str_index,
|
ctx->str_index,
|
||||||
ctx->total_qbuf_bytes,
|
ctx->total_qbuf_bytes,
|
||||||
ctx->total_ts_bytes,
|
ctx->total_write_bytes);
|
||||||
ctx->total_write_bytes,
|
|
||||||
ctx->total_consumed_bytes);
|
|
||||||
update_wptr(ctx, pStrBufDesc, pStrBufDesc->rptr);
|
update_wptr(ctx, pStrBufDesc, pStrBufDesc->rptr);
|
||||||
ctx->pre_pic_end_addr = pStrBufDesc->rptr;
|
|
||||||
ctx->beginning = pStrBufDesc->rptr;
|
ctx->beginning = pStrBufDesc->rptr;
|
||||||
ctx->total_qbuf_bytes = 0;
|
ctx->total_qbuf_bytes = 0;
|
||||||
ctx->total_write_bytes = 0;
|
ctx->total_write_bytes = 0;
|
||||||
ctx->total_consumed_bytes = 0;
|
|
||||||
ctx->total_ts_bytes = 0;
|
|
||||||
ctx->tsm_sync_flag = true;
|
|
||||||
up(&queue->drv_q_lock);
|
up(&queue->drv_q_lock);
|
||||||
|
|
||||||
ctx->frm_dis_delay = 0;
|
ctx->frm_dis_delay = 0;
|
||||||
|
@ -5438,7 +5252,7 @@ static ssize_t show_instance_command_info(struct device *dev,
|
||||||
statistic = &ctx->statistic;
|
statistic = &ctx->statistic;
|
||||||
|
|
||||||
num += scnprintf(buf + num, PAGE_SIZE - num, "command number:\n");
|
num += scnprintf(buf + num, PAGE_SIZE - num, "command number:\n");
|
||||||
for (i = VID_API_CMD_NULL; i < VID_API_CMD_YUV_READY + 1; i++) {
|
for (i = VID_API_CMD_NULL; i < VID_API_CMD_TS + 1; i++) {
|
||||||
size = scnprintf(buf + num, PAGE_SIZE - num,
|
size = scnprintf(buf + num, PAGE_SIZE - num,
|
||||||
"\t%40s(%2d):%16ld\n",
|
"\t%40s(%2d):%16ld\n",
|
||||||
cmd2str[i], i, statistic->cmd[i]);
|
cmd2str[i], i, statistic->cmd[i]);
|
||||||
|
@ -5446,7 +5260,7 @@ static ssize_t show_instance_command_info(struct device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
num += scnprintf(buf + num, PAGE_SIZE - num, "\t%40s :%16ld\n",
|
num += scnprintf(buf + num, PAGE_SIZE - num, "\t%40s :%16ld\n",
|
||||||
"UNKNOWN COMMAND", statistic->cmd[VID_API_CMD_YUV_READY + 1]);
|
"UNKNOWN COMMAND", statistic->cmd[VID_API_CMD_TS + 1]);
|
||||||
|
|
||||||
num += scnprintf(buf + num, PAGE_SIZE - num, "current command:\n");
|
num += scnprintf(buf + num, PAGE_SIZE - num, "current command:\n");
|
||||||
num += scnprintf(buf + num, PAGE_SIZE - num,
|
num += scnprintf(buf + num, PAGE_SIZE - num,
|
||||||
|
@ -5572,9 +5386,6 @@ static ssize_t show_instance_buffer_info(struct device *dev,
|
||||||
num += scnprintf(buf + num, PAGE_SIZE - num,
|
num += scnprintf(buf + num, PAGE_SIZE - num,
|
||||||
"\t%40s:%16d\n", "total frame number",
|
"\t%40s:%16d\n", "total frame number",
|
||||||
ctx->frm_total_num);
|
ctx->frm_total_num);
|
||||||
num += scnprintf(buf + num, PAGE_SIZE - num,
|
|
||||||
"\t%40s:%16d\n", "timestamp delay frame",
|
|
||||||
getTSManagerPreBufferCnt(ctx->tsm));
|
|
||||||
num += scnprintf(buf + num, PAGE_SIZE - num,
|
num += scnprintf(buf + num, PAGE_SIZE - num,
|
||||||
"\t%40s:%16lld\n", "timestamp threshold(ms)",
|
"\t%40s:%16lld\n", "timestamp threshold(ms)",
|
||||||
ctx->ts_threshold);
|
ctx->ts_threshold);
|
||||||
|
@ -6159,12 +5970,6 @@ static int v4l2_open(struct file *filp)
|
||||||
ctx->quantization = V4L2_QUANTIZATION_LIM_RANGE;
|
ctx->quantization = V4L2_QUANTIZATION_LIM_RANGE;
|
||||||
INIT_LIST_HEAD(&ctx->cmd_q);
|
INIT_LIST_HEAD(&ctx->cmd_q);
|
||||||
INIT_LIST_HEAD(&ctx->perf_q);
|
INIT_LIST_HEAD(&ctx->perf_q);
|
||||||
ctx->tsm = createTSManager(tsm_buffer_size);
|
|
||||||
if (!ctx->tsm)
|
|
||||||
goto err_create_tsm;
|
|
||||||
sema_init(&ctx->tsm_lock, 1);
|
|
||||||
resyncTSManager(ctx->tsm, 0, tsm_mode);
|
|
||||||
ctx->tsm_sync_flag = false;
|
|
||||||
ctx->output_ts = TSM_TIMESTAMP_NONE;
|
ctx->output_ts = TSM_TIMESTAMP_NONE;
|
||||||
ctx->capture_ts = TSM_TIMESTAMP_NONE;
|
ctx->capture_ts = TSM_TIMESTAMP_NONE;
|
||||||
create_instance_file(ctx);
|
create_instance_file(ctx);
|
||||||
|
@ -6201,6 +6006,7 @@ static int v4l2_open(struct file *filp)
|
||||||
create_fwlog_file(ctx->dev);
|
create_fwlog_file(ctx->dev);
|
||||||
create_dbglog_file(ctx->dev);
|
create_dbglog_file(ctx->dev);
|
||||||
mutex_unlock(&dev->dev_mutex);
|
mutex_unlock(&dev->dev_mutex);
|
||||||
|
rpc_init_instance(&dev->shared_mem, ctx->str_index);
|
||||||
rpc_set_stream_cfg_value(dev->shared_mem.pSharedInterface, ctx->str_index, vpu_dbe_num);
|
rpc_set_stream_cfg_value(dev->shared_mem.pSharedInterface, ctx->str_index, vpu_dbe_num);
|
||||||
init_vpu_buffer(ctx);
|
init_vpu_buffer(ctx);
|
||||||
|
|
||||||
|
@ -6218,10 +6024,6 @@ err_firmware_load:
|
||||||
if (vpu_frmcrcdump_ena)
|
if (vpu_frmcrcdump_ena)
|
||||||
close_crc_file(ctx);
|
close_crc_file(ctx);
|
||||||
err_open_crc:
|
err_open_crc:
|
||||||
if (ctx->tsm)
|
|
||||||
destroyTSManager(ctx->tsm);
|
|
||||||
ctx->tsm = NULL;
|
|
||||||
err_create_tsm:
|
|
||||||
remove_instance_file(ctx);
|
remove_instance_file(ctx);
|
||||||
dev->ctx[idx] = NULL;
|
dev->ctx[idx] = NULL;
|
||||||
err_init_kfifo:
|
err_init_kfifo:
|
||||||
|
@ -6315,10 +6117,6 @@ static int v4l2_release(struct file *filp)
|
||||||
if (ctx->instance_wq)
|
if (ctx->instance_wq)
|
||||||
destroy_workqueue(ctx->instance_wq);
|
destroy_workqueue(ctx->instance_wq);
|
||||||
|
|
||||||
if (ctx->tsm) {
|
|
||||||
destroyTSManager(ctx->tsm);
|
|
||||||
ctx->tsm = NULL;
|
|
||||||
}
|
|
||||||
if (vpu_frmcrcdump_ena)
|
if (vpu_frmcrcdump_ena)
|
||||||
close_crc_file(ctx);
|
close_crc_file(ctx);
|
||||||
ctrls_delete_decoder(ctx);
|
ctrls_delete_decoder(ctx);
|
||||||
|
@ -7039,12 +6837,6 @@ module_param(vpu_frmcrcdump_ena, int, 0644);
|
||||||
MODULE_PARM_DESC(vpu_frmcrcdump_ena, "enable frame crc dump(0-1)");
|
MODULE_PARM_DESC(vpu_frmcrcdump_ena, "enable frame crc dump(0-1)");
|
||||||
module_param(stream_buffer_threshold, int, 0644);
|
module_param(stream_buffer_threshold, int, 0644);
|
||||||
MODULE_PARM_DESC(stream_buffer_threshold, "stream buffer threshold");
|
MODULE_PARM_DESC(stream_buffer_threshold, "stream buffer threshold");
|
||||||
module_param(tsm_mode, int, 0644);
|
|
||||||
MODULE_PARM_DESC(tsm_mode, "timestamp manager mode(0 : ai, 1 : fifo)");
|
|
||||||
module_param(tsm_buffer_size, int, 0644);
|
|
||||||
MODULE_PARM_DESC(tsm_buffer_size, "timestamp manager buffer size");
|
|
||||||
module_param(tsm_use_consumed_length, int, 0644);
|
|
||||||
MODULE_PARM_DESC(tsm_use_consumed_length, "timestamp manager use consumed length");
|
|
||||||
module_param(precheck_show_bytes, int, 0644);
|
module_param(precheck_show_bytes, int, 0644);
|
||||||
MODULE_PARM_DESC(precheck_show_bytes, "show the beginning of content");
|
MODULE_PARM_DESC(precheck_show_bytes, "show the beginning of content");
|
||||||
module_param(vpu_show_perf_ena, int, 0644);
|
module_param(vpu_show_perf_ena, int, 0644);
|
||||||
|
|
|
@ -68,7 +68,8 @@ extern unsigned int vpu_dbg_level_decoder;
|
||||||
#define VPU_DISABLE_BITS (0x7)
|
#define VPU_DISABLE_BITS (0x7)
|
||||||
|
|
||||||
#define V4L2_PIX_FMT_NV12_10BIT v4l2_fourcc('N', 'T', '1', '2') /* Y/CbCr 4:2:0 for 10bit */
|
#define V4L2_PIX_FMT_NV12_10BIT v4l2_fourcc('N', 'T', '1', '2') /* Y/CbCr 4:2:0 for 10bit */
|
||||||
#define INVALID_FRAME_DEPTH -1
|
#define VPU_FRAME_DEPTH_MAX 512
|
||||||
|
#define VPU_FRAME_DEPTH_DEFAULT 256
|
||||||
#define DECODER_NODE_NUMBER 12 // use /dev/video12 as vpu decoder
|
#define DECODER_NODE_NUMBER 12 // use /dev/video12 as vpu decoder
|
||||||
#define DEFAULT_LOG_DEPTH 20
|
#define DEFAULT_LOG_DEPTH 20
|
||||||
#define DEFAULT_FRMDBG_ENABLE 0
|
#define DEFAULT_FRMDBG_ENABLE 0
|
||||||
|
@ -342,7 +343,7 @@ struct vpu_dev {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vpu_statistic {
|
struct vpu_statistic {
|
||||||
unsigned long cmd[VID_API_CMD_YUV_READY + 2];
|
unsigned long cmd[VID_API_CMD_TS + 2];
|
||||||
unsigned long event[VID_API_EVENT_DEC_CFG_INFO + 2];
|
unsigned long event[VID_API_EVENT_DEC_CFG_INFO + 2];
|
||||||
unsigned long current_cmd;
|
unsigned long current_cmd;
|
||||||
unsigned long current_event;
|
unsigned long current_event;
|
||||||
|
@ -462,15 +463,9 @@ struct vpu_ctx {
|
||||||
int frm_dec_delay;
|
int frm_dec_delay;
|
||||||
int frm_total_num;
|
int frm_total_num;
|
||||||
|
|
||||||
void *tsm;
|
|
||||||
bool tsm_sync_flag;
|
|
||||||
u32 pre_pic_end_addr;
|
|
||||||
long total_qbuf_bytes;
|
long total_qbuf_bytes;
|
||||||
long total_write_bytes;
|
long total_write_bytes;
|
||||||
long total_consumed_bytes;
|
|
||||||
long total_ts_bytes;
|
|
||||||
u32 extra_size;
|
u32 extra_size;
|
||||||
struct semaphore tsm_lock;
|
|
||||||
s64 output_ts;
|
s64 output_ts;
|
||||||
s64 capture_ts;
|
s64 capture_ts;
|
||||||
s64 ts_threshold;
|
s64 ts_threshold;
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
|
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
#include "vpu_rpc.h"
|
#include "vpu_rpc.h"
|
||||||
|
|
||||||
void rpc_init_shared_memory(struct shared_addr *This,
|
void rpc_init_shared_memory(struct shared_addr *This,
|
||||||
|
@ -331,6 +332,7 @@ void rpc_send_cmd_buf(struct shared_addr *This,
|
||||||
{
|
{
|
||||||
pDEC_RPC_HOST_IFACE pSharedInterface = (pDEC_RPC_HOST_IFACE)This->shared_mem_vir;
|
pDEC_RPC_HOST_IFACE pSharedInterface = (pDEC_RPC_HOST_IFACE)This->shared_mem_vir;
|
||||||
MediaIPFW_Video_BufDesc *pCmdDesc = &pSharedInterface->StreamCmdBufferDesc;
|
MediaIPFW_Video_BufDesc *pCmdDesc = &pSharedInterface->StreamCmdBufferDesc;
|
||||||
|
BUFFER_DESCRIPTOR_TYPE *desc = NULL;
|
||||||
u_int32 *cmddata;
|
u_int32 *cmddata;
|
||||||
u_int32 i;
|
u_int32 i;
|
||||||
u_int32 *cmdword = (u_int32 *)(This->cmd_mem_vir+pCmdDesc->uWrPtr - pCmdDesc->uStart);
|
u_int32 *cmdword = (u_int32 *)(This->cmd_mem_vir+pCmdDesc->uWrPtr - pCmdDesc->uStart);
|
||||||
|
@ -358,6 +360,12 @@ void rpc_send_cmd_buf(struct shared_addr *This,
|
||||||
*cmddata = local_cmddata[i];
|
*cmddata = local_cmddata[i];
|
||||||
rpc_update_cmd_buffer_ptr(pCmdDesc);
|
rpc_update_cmd_buffer_ptr(pCmdDesc);
|
||||||
}
|
}
|
||||||
|
if (cmdid != VID_API_CMD_FIRM_RESET) {
|
||||||
|
desc = &pSharedInterface->StreamApiCmdBufferDesc[idx];
|
||||||
|
desc->wptr++;
|
||||||
|
if (desc->wptr >= desc->end)
|
||||||
|
desc->wptr = desc->start;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u_int32 rpc_MediaIPFW_Video_message_check(struct shared_addr *This)
|
u_int32 rpc_MediaIPFW_Video_message_check(struct shared_addr *This)
|
||||||
|
@ -424,3 +432,56 @@ void rpc_receive_msg_buf(struct shared_addr *This, struct event_msg *msg)
|
||||||
rpc_update_msg_buffer_ptr(pMsgDesc);
|
rpc_update_msg_buffer_ptr(pMsgDesc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool check_is_ready(struct shared_addr *This, u32 idx)
|
||||||
|
{
|
||||||
|
pDEC_RPC_HOST_IFACE pSharedInterface = NULL;
|
||||||
|
BUFFER_DESCRIPTOR_TYPE *desc = NULL;
|
||||||
|
u32 size;
|
||||||
|
u32 rptr;
|
||||||
|
u32 wptr;
|
||||||
|
u32 used;
|
||||||
|
|
||||||
|
if (!This || !This->shared_mem_vir || idx >= VID_API_NUM_STREAMS)
|
||||||
|
return false;
|
||||||
|
pSharedInterface = This->shared_mem_vir;
|
||||||
|
desc = &pSharedInterface->StreamApiCmdBufferDesc[idx];
|
||||||
|
size = desc->end - desc->start;
|
||||||
|
rptr = desc->rptr;
|
||||||
|
wptr = desc->wptr;
|
||||||
|
used = (wptr + size - rptr) % size;
|
||||||
|
if (!size || used < size / 2)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rpc_check_is_ready(struct shared_addr *This, u32 idx)
|
||||||
|
{
|
||||||
|
u32 cnt = 0;
|
||||||
|
|
||||||
|
if (!This || !This->shared_mem_vir || idx >= VID_API_NUM_STREAMS)
|
||||||
|
return false;
|
||||||
|
while (!check_is_ready(This, idx)) {
|
||||||
|
if (cnt > 30)
|
||||||
|
return false;
|
||||||
|
mdelay(1);
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rpc_init_instance(struct shared_addr *This, u32 idx)
|
||||||
|
{
|
||||||
|
pDEC_RPC_HOST_IFACE pSharedInterface = NULL;
|
||||||
|
BUFFER_DESCRIPTOR_TYPE *desc = NULL;
|
||||||
|
|
||||||
|
if (!This || !This->shared_mem_vir || idx >= VID_API_NUM_STREAMS)
|
||||||
|
return;
|
||||||
|
pSharedInterface = This->shared_mem_vir;
|
||||||
|
desc = &pSharedInterface->StreamApiCmdBufferDesc[idx];
|
||||||
|
desc->wptr = desc->rptr;
|
||||||
|
if (desc->wptr >= desc->end)
|
||||||
|
desc->wptr = desc->start;
|
||||||
|
}
|
||||||
|
|
|
@ -118,5 +118,7 @@ void rpc_send_cmd_buf(struct shared_addr *This,
|
||||||
u_int32 *local_cmddata);
|
u_int32 *local_cmddata);
|
||||||
void rpc_receive_msg_buf(struct shared_addr *This, struct event_msg *msg);
|
void rpc_receive_msg_buf(struct shared_addr *This, struct event_msg *msg);
|
||||||
u_int32 rpc_MediaIPFW_Video_message_check(struct shared_addr *This);
|
u_int32 rpc_MediaIPFW_Video_message_check(struct shared_addr *This);
|
||||||
|
bool rpc_check_is_ready(struct shared_addr *This, u32 idx);
|
||||||
|
void rpc_init_instance(struct shared_addr *This, u32 idx);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,612 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2018-2019 NXP
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The code contained herein is licensed under the GNU General Public
|
|
||||||
* License. You may obtain a copy of the GNU General Public License
|
|
||||||
* Version 2 or later at the following locations:
|
|
||||||
*
|
|
||||||
* http://www.opensource.org/licenses/gpl-license.html
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Module Name: TimeStamp.c
|
|
||||||
*
|
|
||||||
* Description: include TimeStamp stratege for VPU / SW video decoder plugin
|
|
||||||
*
|
|
||||||
* Portability: This code is written for Linux OS and Gstreamer
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/string.h>
|
|
||||||
|
|
||||||
#include "vpu_ts.h"
|
|
||||||
|
|
||||||
int debug_level;
|
|
||||||
|
|
||||||
static void tsm_free_received_entry(TSMRecivedCtl *rctl,
|
|
||||||
TSMReceivedEntry *entry)
|
|
||||||
{
|
|
||||||
entry->next = rctl->free;
|
|
||||||
rctl->free = entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static TSMReceivedEntry *tsm_new_received_entry(TSMRecivedCtl *rctl)
|
|
||||||
{
|
|
||||||
TSMReceivedEntry *ret = NULL;
|
|
||||||
|
|
||||||
if (rctl->free) {
|
|
||||||
ret = rctl->free;
|
|
||||||
rctl->free = ret->next;
|
|
||||||
} else {
|
|
||||||
TSMReceivedEntryMemory *p = kzalloc(sizeof(TSMReceivedEntryMemory), GFP_KERNEL);
|
|
||||||
|
|
||||||
if (p) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 1; i < TSM_RECEIVED_NUNBER; i++) {
|
|
||||||
TSMReceivedEntry *e = &p->entrys[i];
|
|
||||||
|
|
||||||
tsm_free_received_entry(rctl, e);
|
|
||||||
};
|
|
||||||
p->next = rctl->memory;
|
|
||||||
rctl->memory = p;
|
|
||||||
ret = p->entrys;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TSManagerReceive2(void *handle, TSM_TIMESTAMP timestamp, int size)
|
|
||||||
{
|
|
||||||
#define CLEAR_TSM_RENTRY(entry)\
|
|
||||||
do { \
|
|
||||||
(entry)->used = 0; \
|
|
||||||
(entry)->next = NULL; \
|
|
||||||
} while (0)
|
|
||||||
TSManager *tsm = (TSManager *) handle;
|
|
||||||
|
|
||||||
TSM_VERBOSE("receive2 %u:%02u:%02u.%09u size %d\n",
|
|
||||||
TSM_TIME_H(timestamp),
|
|
||||||
TSM_TIME_M(timestamp),
|
|
||||||
TSM_TIME_S(timestamp),
|
|
||||||
TSM_TIME_NS(timestamp),
|
|
||||||
size);
|
|
||||||
|
|
||||||
if (tsm) {
|
|
||||||
if (size > 0) {
|
|
||||||
TSMRecivedCtl *rctl = &tsm->rctl;
|
|
||||||
TSMReceivedEntry *e = tsm_new_received_entry(rctl);
|
|
||||||
|
|
||||||
if (e) {
|
|
||||||
CLEAR_TSM_RENTRY(e);
|
|
||||||
e->ts = timestamp;
|
|
||||||
e->size = size;
|
|
||||||
if (rctl->tail) {
|
|
||||||
rctl->tail->next = e;
|
|
||||||
rctl->tail = e;
|
|
||||||
} else
|
|
||||||
rctl->head = rctl->tail = e;
|
|
||||||
}
|
|
||||||
rctl->cnt++;
|
|
||||||
} else
|
|
||||||
TSManagerReceive(handle, timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static TSM_TIMESTAMP TSManagerGetLastTimeStamp(TSMRecivedCtl *rctl,
|
|
||||||
int size, int use)
|
|
||||||
{
|
|
||||||
TSM_TIMESTAMP ts = TSM_TIMESTAMP_NONE;
|
|
||||||
TSMReceivedEntry *e;
|
|
||||||
|
|
||||||
while ((size > 0) && (e = rctl->head)) {
|
|
||||||
if (TSM_TS_IS_VALID(e->ts))
|
|
||||||
ts = ((e->used) ? (TSM_TIMESTAMP_NONE) : (e->ts));
|
|
||||||
|
|
||||||
TSM_VERBOSE("ts get: %u:%02u:%02u.%09u\n",
|
|
||||||
TSM_TIME_H(ts),
|
|
||||||
TSM_TIME_M(ts),
|
|
||||||
TSM_TIME_S(ts),
|
|
||||||
TSM_TIME_NS(ts));
|
|
||||||
|
|
||||||
if (use)
|
|
||||||
e->used = 1;
|
|
||||||
if (size >= e->size) {
|
|
||||||
rctl->head = e->next;
|
|
||||||
if (rctl->head == NULL)
|
|
||||||
rctl->tail = NULL;
|
|
||||||
size -= e->size;
|
|
||||||
rctl->cnt--;
|
|
||||||
tsm_free_received_entry(rctl, e);
|
|
||||||
} else {
|
|
||||||
e->size -= size;
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TSManagerFlush2(void *handle, int size)
|
|
||||||
{
|
|
||||||
TSManager *tsm = (TSManager *) handle;
|
|
||||||
|
|
||||||
if (tsm)
|
|
||||||
TSManagerGetLastTimeStamp(&tsm->rctl, size, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*======================================================================================
|
|
||||||
FUNCTION: mfw_gst_receive_ts
|
|
||||||
|
|
||||||
DESCRIPTION: Check timestamp and do frame dropping if enabled
|
|
||||||
|
|
||||||
ARGUMENTS PASSED: pTimeStamp_Object - TimeStamp Manager to handle related timestamp
|
|
||||||
timestamp - time stamp of the input buffer which has video data.
|
|
||||||
RETURN VALUE: None
|
|
||||||
PRE-CONDITIONS: None
|
|
||||||
POST-CONDITIONS: None
|
|
||||||
IMPORTANT NOTES: None
|
|
||||||
=======================================================================================*/
|
|
||||||
static void _TSManagerReceive(void *handle, TSM_TIMESTAMP timestamp, void *key)
|
|
||||||
{
|
|
||||||
TSManager *tsm = (TSManager *) handle;
|
|
||||||
|
|
||||||
if (tsm) {
|
|
||||||
if (TSM_TS_IS_VALID(timestamp) && (tsm->rx_cnt))
|
|
||||||
tsm->valid_ts_received = 1;
|
|
||||||
tsm->rx_cnt++;
|
|
||||||
if (tsm->cnt < tsm->ts_buf_size - 1) {
|
|
||||||
tsm->cnt++;
|
|
||||||
if (tsm->mode == MODE_AI) {
|
|
||||||
if (TSM_TS_IS_VALID(timestamp)) {
|
|
||||||
if (tsm->first_rx) {
|
|
||||||
tsm->last_ts_received = timestamp;
|
|
||||||
tsm->first_rx = 0;
|
|
||||||
} else {
|
|
||||||
if (tsm->suspicious_ts) {
|
|
||||||
if (timestamp >= tsm->suspicious_ts)
|
|
||||||
tsm->last_ts_received = timestamp;
|
|
||||||
tsm->suspicious_ts = 0;
|
|
||||||
}
|
|
||||||
if ((timestamp > tsm->last_ts_received)
|
|
||||||
&& (timestamp - tsm->last_ts_received > tsm->discont_threshold)) {
|
|
||||||
tsm->suspicious_ts = timestamp;
|
|
||||||
timestamp = TSM_TIMESTAMP_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TSM_TS_IS_VALID(timestamp)) { // && (TSM_ABS(timestamp, tsm->last_ts_sent)<TSM_SECOND*10))
|
|
||||||
tsm->ts_buf[tsm->rx].ts = timestamp;
|
|
||||||
tsm->ts_buf[tsm->rx].age = tsm->age + TSM_PLUS_AGE(tsm);
|
|
||||||
tsm->ts_buf[tsm->rx].key = key;
|
|
||||||
tsm->last_ts_received = timestamp;
|
|
||||||
#ifdef DEBUG
|
|
||||||
//printf("age should %lld %lld\n", tsm->age, tsm->ts_buf[tsm->rx].age);
|
|
||||||
//printf("++++++ distance = %d tx=%d, rx=%d, invalid count=%d\n", TSM_DISTANCE(tsm), tsm->tx, tsm->rx,tsm->invalid_ts_count);
|
|
||||||
#endif
|
|
||||||
tsm->rx = ((tsm->rx + 1) % tsm->ts_buf_size);
|
|
||||||
} else
|
|
||||||
tsm->invalid_ts_count++;
|
|
||||||
} else if (tsm->mode == MODE_FIFO) {
|
|
||||||
tsm->ts_buf[tsm->rx].ts = timestamp;
|
|
||||||
tsm->rx = ((tsm->rx + 1) % tsm->ts_buf_size);
|
|
||||||
}
|
|
||||||
TSM_LOG("++Receive %d:%u:%02u:%02u.%09u, invalid:%d, size:%d key %p\n",
|
|
||||||
tsm->rx_cnt,
|
|
||||||
TSM_TIME_H(timestamp),
|
|
||||||
TSM_TIME_M(timestamp),
|
|
||||||
TSM_TIME_S(timestamp),
|
|
||||||
TSM_TIME_NS(timestamp),
|
|
||||||
tsm->invalid_ts_count,
|
|
||||||
tsm->cnt,
|
|
||||||
key);
|
|
||||||
} else
|
|
||||||
TSM_ERROR("Too many timestamps recieved!! (cnt=%d)\n", tsm->cnt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TSManagerValid2(void *handle, int size, void *key)
|
|
||||||
{
|
|
||||||
TSManager *tsm = (TSManager *) handle;
|
|
||||||
|
|
||||||
TSM_VERBOSE("valid2 size %d\n", size);
|
|
||||||
|
|
||||||
if (tsm) {
|
|
||||||
TSM_TIMESTAMP ts;
|
|
||||||
|
|
||||||
ts = TSManagerGetLastTimeStamp(&tsm->rctl, size, 1);
|
|
||||||
TSM_VERBOSE("TSManagerGetLastTimeStamp: %u:%02u:%02u.%09u\n",
|
|
||||||
TSM_TIME_H(ts),
|
|
||||||
TSM_TIME_M(ts),
|
|
||||||
TSM_TIME_S(ts),
|
|
||||||
TSM_TIME_NS(ts));
|
|
||||||
_TSManagerReceive(tsm, ts, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TSManagerReceive(void *handle, TSM_TIMESTAMP timestamp)
|
|
||||||
{
|
|
||||||
_TSManagerReceive(handle, timestamp, TSM_KEY_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*======================================================================================
|
|
||||||
FUNCTION: TSManagerSend
|
|
||||||
|
|
||||||
DESCRIPTION: Check timestamp and do frame dropping if enabled
|
|
||||||
|
|
||||||
ARGUMENTS PASSED: pTimeStamp_Object - TimeStamp Manager to handle related timestamp
|
|
||||||
ptimestamp - returned timestamp to use at render
|
|
||||||
|
|
||||||
RETURN VALUE: None
|
|
||||||
PRE-CONDITIONS: None
|
|
||||||
POST-CONDITIONS: None
|
|
||||||
IMPORTANT NOTES: None
|
|
||||||
=======================================================================================*/
|
|
||||||
static TSM_TIMESTAMP _TSManagerSend2(void *handle, void *key, int send)
|
|
||||||
{
|
|
||||||
TSManager *tsm = (TSManager *) handle;
|
|
||||||
int i;
|
|
||||||
int index = -1;
|
|
||||||
int isValidTs = 0;
|
|
||||||
TSM_TIMESTAMP ts0 = 0, tstmp = TSM_TIMESTAMP_NONE;
|
|
||||||
unsigned long long age = 0;
|
|
||||||
TSM_TIMESTAMP half_interval;
|
|
||||||
|
|
||||||
if (tsm == NULL)
|
|
||||||
return tstmp;
|
|
||||||
|
|
||||||
i = tsm->tx;
|
|
||||||
half_interval = TSM_ADAPTIVE_INTERVAL (tsm) >> 1;
|
|
||||||
|
|
||||||
if (tsm) {
|
|
||||||
if (send)
|
|
||||||
tsm->tx_cnt++;
|
|
||||||
else {
|
|
||||||
tsm->cnt++;
|
|
||||||
tsm->invalid_ts_count++;
|
|
||||||
}
|
|
||||||
if (tsm->cnt > 0) {
|
|
||||||
if (send)
|
|
||||||
tsm->cnt--;
|
|
||||||
|
|
||||||
if (tsm->mode == MODE_AI) {
|
|
||||||
if (tsm->first_tx == 0)
|
|
||||||
tstmp = tsm->last_ts_sent + TSM_ADAPTIVE_INTERVAL(tsm);
|
|
||||||
else
|
|
||||||
tstmp = tsm->last_ts_sent;
|
|
||||||
|
|
||||||
while (i != tsm->rx) {
|
|
||||||
if (index >= 0) {
|
|
||||||
if (tsm->ts_buf[i].ts < ts0) {
|
|
||||||
ts0 = tsm->ts_buf[i].ts;
|
|
||||||
age = tsm->ts_buf[i].age;
|
|
||||||
index = i;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ts0 = tsm->ts_buf[i].ts;
|
|
||||||
age = tsm->ts_buf[i].age;
|
|
||||||
index = i;
|
|
||||||
}
|
|
||||||
if ((TSM_KEY_IS_VALID(key)) && (key == tsm->ts_buf[i].key))
|
|
||||||
break;
|
|
||||||
i = ((i + 1) % tsm->ts_buf_size);
|
|
||||||
}
|
|
||||||
if (index >= 0) {
|
|
||||||
if ((tsm->invalid_ts_count) && (ts0 >= ((tstmp) + half_interval))
|
|
||||||
&& (age > tsm->age)) {
|
|
||||||
/* use calculated ts0 */
|
|
||||||
if (send)
|
|
||||||
tsm->invalid_ts_count--;
|
|
||||||
} else {
|
|
||||||
if (send) {
|
|
||||||
if (index != tsm->tx)
|
|
||||||
tsm->ts_buf[index] = tsm->ts_buf[tsm->tx];
|
|
||||||
|
|
||||||
tsm->tx = ((tsm->tx + 1) % tsm->ts_buf_size);
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
if (ts0 >= ((tstmp) + half_interval))
|
|
||||||
tstmp = tstmp;
|
|
||||||
else
|
|
||||||
tstmp = ts0;
|
|
||||||
#else
|
|
||||||
tstmp = ts0;
|
|
||||||
#endif
|
|
||||||
isValidTs = 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (send)
|
|
||||||
tsm->invalid_ts_count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsm->first_tx == 0) {
|
|
||||||
if (tstmp > tsm->last_ts_sent)
|
|
||||||
ts0 = (tstmp - tsm->last_ts_sent);
|
|
||||||
else {
|
|
||||||
ts0 = 0;
|
|
||||||
//reset the timestamp to last frame only when new frames's timestamp is earlier than one frame.
|
|
||||||
if (tstmp + TSM_ADAPTIVE_INTERVAL(tsm) * 3 / 2 < tsm->last_ts_sent)
|
|
||||||
tstmp = tsm->last_ts_sent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ts0 > TSM_ADAPTIVE_INTERVAL(tsm) * 3 / 2) {
|
|
||||||
TSM_WARNING("Jitter1:%u:%02u:%02u.%09u %u:%02u:%02u.%09u\n",
|
|
||||||
TSM_TIME_H(ts0),
|
|
||||||
TSM_TIME_M(ts0),
|
|
||||||
TSM_TIME_S(ts0),
|
|
||||||
TSM_TIME_NS(ts0),
|
|
||||||
TSM_TIME_H(TSM_ADAPTIVE_INTERVAL(tsm) * 3 / 2),
|
|
||||||
TSM_TIME_M(TSM_ADAPTIVE_INTERVAL(tsm) * 3 / 2),
|
|
||||||
TSM_TIME_S(TSM_ADAPTIVE_INTERVAL(tsm) * 3 / 2),
|
|
||||||
TSM_TIME_NS(TSM_ADAPTIVE_INTERVAL(tsm) * 3 / 2));
|
|
||||||
} else if (ts0 == 0)
|
|
||||||
TSM_WARNING("Jitter:%u:%02u:%02u.%09u\n",
|
|
||||||
TSM_TIME_H(ts0),
|
|
||||||
TSM_TIME_M(ts0),
|
|
||||||
TSM_TIME_S(ts0),
|
|
||||||
TSM_TIME_NS(ts0));
|
|
||||||
|
|
||||||
if (send) {
|
|
||||||
if (isValidTs && ts0 > TSM_ADAPTIVE_INTERVAL(tsm) * 2)
|
|
||||||
ts0 = TSM_ADAPTIVE_INTERVAL(tsm) * 2;
|
|
||||||
if ((ts0 <= TSM_ADAPTIVE_INTERVAL(tsm) * 2) || (tsm->big_cnt > 3)) {
|
|
||||||
tsm->big_cnt = 0;
|
|
||||||
tsm->dur_history_total -=
|
|
||||||
tsm->dur_history_buf[tsm->dur_history_tx];
|
|
||||||
tsm->dur_history_buf[tsm->dur_history_tx] = ts0;
|
|
||||||
tsm->dur_history_tx =
|
|
||||||
((tsm->dur_history_tx + 1) % TSM_HISTORY_SIZE);
|
|
||||||
tsm->dur_history_total += ts0;
|
|
||||||
} else
|
|
||||||
tsm->big_cnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (send) {
|
|
||||||
tsm->last_ts_sent = tstmp;
|
|
||||||
tsm->age++;
|
|
||||||
tsm->first_tx = 0;
|
|
||||||
}
|
|
||||||
} else if (tsm->mode == MODE_FIFO) {
|
|
||||||
tstmp = tsm->ts_buf[tsm->tx].ts;
|
|
||||||
if (send)
|
|
||||||
tsm->tx = ((tsm->tx + 1) % tsm->ts_buf_size);
|
|
||||||
|
|
||||||
ts0 = tstmp - tsm->last_ts_sent;
|
|
||||||
if (send)
|
|
||||||
tsm->last_ts_sent = tstmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (send) {
|
|
||||||
TSM_LOG("--Send %d:%u:%02u:%02u.%09u, int:%u:%02u:%02u.%09u, avg:%u:%02u:%02u.%09u inkey %p\n",
|
|
||||||
tsm->tx_cnt,
|
|
||||||
TSM_TIME_H(tstmp),
|
|
||||||
TSM_TIME_M(tstmp),
|
|
||||||
TSM_TIME_S(tstmp),
|
|
||||||
TSM_TIME_NS(tstmp),
|
|
||||||
TSM_TIME_H(ts0),
|
|
||||||
TSM_TIME_M(ts0),
|
|
||||||
TSM_TIME_S(ts0),
|
|
||||||
TSM_TIME_NS(ts0),
|
|
||||||
TSM_TIME_H(TSM_ADAPTIVE_INTERVAL(tsm)),
|
|
||||||
TSM_TIME_M(TSM_ADAPTIVE_INTERVAL(tsm)),
|
|
||||||
TSM_TIME_S(TSM_ADAPTIVE_INTERVAL(tsm)),
|
|
||||||
TSM_TIME_NS(TSM_ADAPTIVE_INTERVAL(tsm)),
|
|
||||||
key);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (tsm->valid_ts_received == 0) {
|
|
||||||
if (tsm->first_tx)
|
|
||||||
tstmp = tsm->last_ts_sent;
|
|
||||||
else
|
|
||||||
tstmp = tsm->last_ts_sent + TSM_ADAPTIVE_INTERVAL(tsm);
|
|
||||||
|
|
||||||
if (send) {
|
|
||||||
tsm->first_tx = 0;
|
|
||||||
tsm->last_ts_sent = tstmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TSM_ERROR("Too many timestamps send!!\n");
|
|
||||||
}
|
|
||||||
if (send == 0) {
|
|
||||||
tsm->cnt--;
|
|
||||||
tsm->invalid_ts_count--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return tstmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TSM_TIMESTAMP TSManagerSend2(void *handle, void *key)
|
|
||||||
{
|
|
||||||
return _TSManagerSend2(handle, key, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TSM_TIMESTAMP TSManagerQuery2(void *handle, void *key)
|
|
||||||
{
|
|
||||||
return _TSManagerSend2(handle, key, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TSM_TIMESTAMP TSManagerSend(void *handle)
|
|
||||||
{
|
|
||||||
return TSManagerSend2(handle, TSM_KEY_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TSM_TIMESTAMP TSManagerQuery(void *handle)
|
|
||||||
{
|
|
||||||
return TSManagerQuery2(handle, TSM_KEY_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void resyncTSManager(void *handle, TSM_TIMESTAMP synctime, TSMGR_MODE mode)
|
|
||||||
{
|
|
||||||
TSManager *tsm = (TSManager *) handle;
|
|
||||||
|
|
||||||
if (tsm) {
|
|
||||||
TSMRecivedCtl *rctl = &tsm->rctl;
|
|
||||||
TSMReceivedEntry *e = rctl->head;
|
|
||||||
|
|
||||||
while ((e = rctl->head)) {
|
|
||||||
rctl->head = e->next;
|
|
||||||
tsm_free_received_entry(rctl, e);
|
|
||||||
};
|
|
||||||
rctl->cnt = 0;
|
|
||||||
|
|
||||||
rctl->tail = NULL;
|
|
||||||
|
|
||||||
tsm->first_tx = 1;
|
|
||||||
tsm->first_rx = 1;
|
|
||||||
tsm->suspicious_ts = 0;
|
|
||||||
|
|
||||||
if (TSM_TS_IS_VALID(synctime))
|
|
||||||
tsm->last_ts_sent = synctime;
|
|
||||||
|
|
||||||
tsm->tx = tsm->rx = 0;
|
|
||||||
tsm->invalid_ts_count = 0;
|
|
||||||
tsm->mode = mode;
|
|
||||||
tsm->age = 0;
|
|
||||||
tsm->rx_cnt = tsm->tx_cnt = tsm->cnt = 0;
|
|
||||||
tsm->valid_ts_received = 0;
|
|
||||||
tsm->big_cnt = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*======================================================================================
|
|
||||||
FUNCTION: mfw_gst_init_ts
|
|
||||||
|
|
||||||
DESCRIPTION: alloc and initialize timestamp strcture
|
|
||||||
|
|
||||||
ARGUMENTS PASSED: ppTimeStamp_Object - pointer of TimeStamp Manager to handle related timestamp
|
|
||||||
|
|
||||||
RETURN VALUE: TimeStamp structure pointer
|
|
||||||
PRE-CONDITIONS: None
|
|
||||||
POST-CONDITIONS: None
|
|
||||||
IMPORTANT NOTES: None
|
|
||||||
=======================================================================================*/
|
|
||||||
void *createTSManager(int ts_buf_size)
|
|
||||||
{
|
|
||||||
TSManager *tsm = (TSManager *) kzalloc(sizeof(TSManager), GFP_KERNEL);
|
|
||||||
|
|
||||||
if (tsm) {
|
|
||||||
memset(tsm, 0, sizeof(TSManager));
|
|
||||||
if (ts_buf_size <= 0)
|
|
||||||
ts_buf_size = TSM_DEFAULT_TS_BUFFER_SIZE;
|
|
||||||
|
|
||||||
tsm->ts_buf_size = ts_buf_size;
|
|
||||||
tsm->ts_buf = kzalloc(sizeof(TSMControl) * ts_buf_size, GFP_KERNEL);
|
|
||||||
|
|
||||||
if (tsm->ts_buf == NULL)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
resyncTSManager(tsm, (TSM_TIMESTAMP) 0, MODE_AI);
|
|
||||||
|
|
||||||
tsm->dur_history_tx = 0;
|
|
||||||
TSM_BUFFER_SET(tsm->dur_history_buf, TSM_DEFAULT_INTERVAL,
|
|
||||||
TSM_HISTORY_SIZE);
|
|
||||||
tsm->dur_history_total = TSM_DEFAULT_INTERVAL << TSM_HISTORY_POWER;
|
|
||||||
|
|
||||||
tsm->discont_threshold = 10000000000LL; // 10s
|
|
||||||
}
|
|
||||||
return tsm;
|
|
||||||
fail:
|
|
||||||
if (tsm) {
|
|
||||||
if (tsm->ts_buf)
|
|
||||||
kfree(tsm->ts_buf);
|
|
||||||
kfree(tsm);
|
|
||||||
tsm = NULL;
|
|
||||||
}
|
|
||||||
return tsm;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void destroyTSManager(void *handle)
|
|
||||||
{
|
|
||||||
TSManager *tsm = (TSManager *) handle;
|
|
||||||
|
|
||||||
if (tsm) {
|
|
||||||
TSMRecivedCtl *rctl = &tsm->rctl;
|
|
||||||
TSMReceivedEntryMemory *rmem;
|
|
||||||
|
|
||||||
if (tsm->ts_buf)
|
|
||||||
kfree(tsm->ts_buf);
|
|
||||||
|
|
||||||
while ((rmem = rctl->memory)) {
|
|
||||||
rctl->memory = rmem->next;
|
|
||||||
kfree(rmem);
|
|
||||||
}
|
|
||||||
kfree(tsm);
|
|
||||||
tsm = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void setTSManagerFrameRate(void *handle, int fps_n, int fps_d)
|
|
||||||
//void setTSManagerFrameRate(void * handle, float framerate)
|
|
||||||
{
|
|
||||||
TSManager *tsm = (TSManager *) handle;
|
|
||||||
TSM_TIMESTAMP ts;
|
|
||||||
|
|
||||||
if ((fps_n > 0) && (fps_d > 0) && (fps_n / fps_d <= 80))
|
|
||||||
ts = TSM_SECOND * fps_d / fps_n;
|
|
||||||
else
|
|
||||||
ts = TSM_DEFAULT_INTERVAL;
|
|
||||||
// TSM_TIMESTAMP ts = TSM_SECOND / framerate;
|
|
||||||
|
|
||||||
if (tsm) {
|
|
||||||
TSM_BUFFER_SET(tsm->dur_history_buf, ts, TSM_HISTORY_SIZE);
|
|
||||||
tsm->dur_history_total = (ts << TSM_HISTORY_POWER);
|
|
||||||
TSM_LOG("Set frame intrval:%u:%02u:%02u.%09u\n",
|
|
||||||
TSM_TIME_H(ts),
|
|
||||||
TSM_TIME_M(ts),
|
|
||||||
TSM_TIME_S(ts),
|
|
||||||
TSM_TIME_NS(ts));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TSM_TIMESTAMP getTSManagerFrameInterval(void *handle)
|
|
||||||
{
|
|
||||||
TSManager *tsm = (TSManager *) handle;
|
|
||||||
TSM_TIMESTAMP ts = 0;
|
|
||||||
|
|
||||||
if (tsm)
|
|
||||||
ts = TSM_ADAPTIVE_INTERVAL(tsm);
|
|
||||||
|
|
||||||
return ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TSM_TIMESTAMP getTSManagerPosition(void *handle)
|
|
||||||
{
|
|
||||||
TSManager *tsm = (TSManager *) handle;
|
|
||||||
TSM_TIMESTAMP ts = 0;
|
|
||||||
|
|
||||||
if (tsm)
|
|
||||||
ts = tsm->last_ts_sent;
|
|
||||||
|
|
||||||
return ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int getTSManagerPreBufferCnt(void *handle)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
TSManager *tsm = (TSManager *) handle;
|
|
||||||
|
|
||||||
if (tsm)
|
|
||||||
i = tsm->rctl.cnt;
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
|
@ -1,251 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2018-2019 NXP
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The code contained herein is licensed under the GNU General Public
|
|
||||||
* License. You may obtain a copy of the GNU General Public License
|
|
||||||
* Version 2 or later at the following locations:
|
|
||||||
*
|
|
||||||
* http://www.opensource.org/licenses/gpl-license.html
|
|
||||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Module Name: TimeStamp.h
|
|
||||||
*
|
|
||||||
* Description: include TimeStamp stratege for VPU / SW video decoder plugin
|
|
||||||
*
|
|
||||||
* Portability: This code is written for Linux OS and Gstreamer
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TIMESTAMP_H_
|
|
||||||
#define _TIMESTAMP_H_
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GST_CLOCK_TIME_NONE:
|
|
||||||
*
|
|
||||||
* Constant to define an undefined clock time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef long long TSM_TIMESTAMP;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
MODE_AI,
|
|
||||||
MODE_FIFO,
|
|
||||||
} TSMGR_MODE;
|
|
||||||
|
|
||||||
#define TSM_TIMESTAMP_NONE ((long long)(-1))
|
|
||||||
#define TSM_KEY_NONE ((void *)0)
|
|
||||||
|
|
||||||
enum {
|
|
||||||
DEBUG_LEVEL_ERROR = 1,
|
|
||||||
DEBUG_LEVEL_WARNING,
|
|
||||||
DEBUG_LEVEL_LOG,
|
|
||||||
DEBUG_LEVEL_VERBOSE,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TSM_MESSAGE(level, fmt, ...) \
|
|
||||||
do { \
|
|
||||||
if (debug_level >= (level)) { \
|
|
||||||
pr_info("TSM:"fmt, ##__VA_ARGS__); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TSM_ERROR(...) TSM_MESSAGE(DEBUG_LEVEL_ERROR, ##__VA_ARGS__)
|
|
||||||
#define TSM_WARNING(...) TSM_MESSAGE(DEBUG_LEVEL_WARNING, ##__VA_ARGS__)
|
|
||||||
#define TSM_LOG(...) TSM_MESSAGE(DEBUG_LEVEL_LOG, ##__VA_ARGS__)
|
|
||||||
#define TSM_VERBOSE(...) TSM_MESSAGE(DEBUG_LEVEL_VERBOSE, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#define TSM_HISTORY_POWER 5
|
|
||||||
#define TSM_HISTORY_SIZE (1 << TSM_HISTORY_POWER)
|
|
||||||
#define TSM_ADAPTIVE_INTERVAL(tsm) \
|
|
||||||
(tsm->dur_history_total >> TSM_HISTORY_POWER)
|
|
||||||
|
|
||||||
#define TSM_SECOND ((TSM_TIMESTAMP)1000000000)
|
|
||||||
#define TSM_DEFAULT_INTERVAL (TSM_SECOND/30)
|
|
||||||
#define TSM_DEFAULT_TS_BUFFER_SIZE (128)
|
|
||||||
|
|
||||||
#define TSM_TS_IS_VALID(ts) \
|
|
||||||
((ts) != TSM_TIMESTAMP_NONE)
|
|
||||||
|
|
||||||
#define TSM_KEY_IS_VALID(key) \
|
|
||||||
((key) != TSM_KEY_NONE)
|
|
||||||
|
|
||||||
#define TSM_DISTANCE(tsm)\
|
|
||||||
(((tsm->rx) >= (tsm->tx))?((tsm->rx)-(tsm->tx)):(tsm->ts_buf_size-(tsm->tx)+(tsm->rx)))
|
|
||||||
|
|
||||||
#define TSM_PLUS_AGE(tsm)\
|
|
||||||
(TSM_DISTANCE(tsm)+tsm->invalid_ts_count+2)
|
|
||||||
|
|
||||||
#define TSM_ABS(ts0, ts1)\
|
|
||||||
(((ts0) > (ts1))?((ts0)-(ts1)):((ts1)-(ts0)))
|
|
||||||
|
|
||||||
#define TSM_TIME_H(t) \
|
|
||||||
(TSM_TS_IS_VALID(t) ? \
|
|
||||||
(unsigned int) (((TSM_TIMESTAMP)(t)) / (TSM_SECOND * 60 * 60)) : 99)
|
|
||||||
#define TSM_TIME_M(t) \
|
|
||||||
(TSM_TS_IS_VALID(t) ? \
|
|
||||||
(unsigned int) ((((TSM_TIMESTAMP)(t)) / (TSM_SECOND * 60)) % 60) : 99)
|
|
||||||
#define TSM_TIME_S(t) \
|
|
||||||
(TSM_TS_IS_VALID(t) ? \
|
|
||||||
(unsigned int) ((((TSM_TIMESTAMP)(t)) / TSM_SECOND) % 60) : 99)
|
|
||||||
#define TSM_TIME_NS(t) \
|
|
||||||
(TSM_TS_IS_VALID(t) ? \
|
|
||||||
(unsigned int) (((TSM_TIMESTAMP)(t)) % TSM_SECOND) : 999999999)
|
|
||||||
|
|
||||||
#define TSM_BUFFER_SET(buf, value, size) \
|
|
||||||
do { \
|
|
||||||
int i; \
|
|
||||||
for (i = 0; i < (size); i++) { \
|
|
||||||
(buf)[i] = (value); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define TSM_RECEIVED_NUNBER 512
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
TSM_TIMESTAMP ts;
|
|
||||||
unsigned long long age;
|
|
||||||
void *key;
|
|
||||||
} TSMControl;
|
|
||||||
|
|
||||||
typedef struct _TSMReceivedEntry {
|
|
||||||
TSM_TIMESTAMP ts;
|
|
||||||
struct _TSMReceivedEntry *next;
|
|
||||||
unsigned int used:1;
|
|
||||||
int size;
|
|
||||||
} TSMReceivedEntry;
|
|
||||||
|
|
||||||
typedef struct _TSMReceivedEntryMemory {
|
|
||||||
struct _TSMReceivedEntryMemory *next;
|
|
||||||
TSMReceivedEntry entrys[TSM_RECEIVED_NUNBER];
|
|
||||||
} TSMReceivedEntryMemory;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
TSMReceivedEntry *head;
|
|
||||||
TSMReceivedEntry *tail;
|
|
||||||
TSMReceivedEntry *free;
|
|
||||||
TSMReceivedEntryMemory *memory;
|
|
||||||
int cnt;
|
|
||||||
} TSMRecivedCtl;
|
|
||||||
|
|
||||||
typedef struct _TSManager {
|
|
||||||
int first_tx;
|
|
||||||
int first_rx;
|
|
||||||
int rx; //timestamps received
|
|
||||||
int tx; //timestamps transferred
|
|
||||||
TSM_TIMESTAMP last_ts_sent; //last time stamp sent
|
|
||||||
TSM_TIMESTAMP last_ts_received;
|
|
||||||
TSM_TIMESTAMP suspicious_ts;
|
|
||||||
|
|
||||||
TSM_TIMESTAMP discont_threshold;
|
|
||||||
|
|
||||||
unsigned int invalid_ts_count;
|
|
||||||
TSMGR_MODE mode;
|
|
||||||
int ts_buf_size;
|
|
||||||
int dur_history_tx;
|
|
||||||
TSM_TIMESTAMP dur_history_total;
|
|
||||||
TSM_TIMESTAMP dur_history_buf[TSM_HISTORY_SIZE];
|
|
||||||
TSMControl *ts_buf;
|
|
||||||
unsigned long long age;
|
|
||||||
int tx_cnt;
|
|
||||||
int rx_cnt;
|
|
||||||
int cnt;
|
|
||||||
unsigned int valid_ts_received:1;
|
|
||||||
int big_cnt;
|
|
||||||
|
|
||||||
TSMRecivedCtl rctl;
|
|
||||||
} TSManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GST_CLOCK_TIME_IS_VALID:
|
|
||||||
* @time: clock time to validate
|
|
||||||
*
|
|
||||||
* Tests if a given #GstClockTime represents a valid defined time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This function receive timestamp into timestamp manager.
|
|
||||||
*
|
|
||||||
* @param handle handle of timestamp manager.
|
|
||||||
*
|
|
||||||
* @param timestamp timestamp received
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
void TSManagerReceive(void *handle, TSM_TIMESTAMP timestamp);
|
|
||||||
void TSManagerReceive2(void *handle, TSM_TIMESTAMP timestamp, int size);
|
|
||||||
void TSManagerFlush2(void *handle, int size);
|
|
||||||
void TSManagerValid2(void *handle, int size, void *key);
|
|
||||||
/*!
|
|
||||||
* This function send the timestamp for next output frame.
|
|
||||||
*
|
|
||||||
* @param handle handle of timestamp manager.
|
|
||||||
*
|
|
||||||
* @return timestamp for next output frame.
|
|
||||||
*/
|
|
||||||
TSM_TIMESTAMP TSManagerSend(void *handle);
|
|
||||||
TSM_TIMESTAMP TSManagerSend2(void *handle, void *key);
|
|
||||||
TSM_TIMESTAMP TSManagerQuery2(void *handle, void *key);
|
|
||||||
TSM_TIMESTAMP TSManagerQuery(void *handle);
|
|
||||||
/*!
|
|
||||||
* This function resync timestamp handler when reset and seek
|
|
||||||
*
|
|
||||||
* @param handle handle of timestamp manager.
|
|
||||||
*
|
|
||||||
* @param synctime the postion time needed to set, if value invalid, position keeps original
|
|
||||||
*
|
|
||||||
* @param mode playing mode (AI or FIFO)
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
void resyncTSManager(void *handle, TSM_TIMESTAMP synctime, TSMGR_MODE mode);
|
|
||||||
/*!
|
|
||||||
* This function create and reset timestamp handler
|
|
||||||
*
|
|
||||||
* @param ts_buf_size time stamp queue buffer size
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
void *createTSManager(int ts_buf_size);
|
|
||||||
/*!
|
|
||||||
* This function destroy timestamp handler
|
|
||||||
*
|
|
||||||
* @param handle handle of timestamp manager.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
void destroyTSManager(void *handle);
|
|
||||||
/*!
|
|
||||||
* This function set history buffer frame interval by fps_n and fps_d
|
|
||||||
*
|
|
||||||
* @param handle handle of timestamp manager.
|
|
||||||
*
|
|
||||||
* @param framerate the framerate to be set
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
void setTSManagerFrameRate(void *handle, int fps_n, int fps_d);
|
|
||||||
// void setTSManagerFrameRate(void * handle, float framerate);
|
|
||||||
/*!
|
|
||||||
* This function set the current calculated Frame Interval
|
|
||||||
*
|
|
||||||
* @param handle handle of timestamp manager.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
TSM_TIMESTAMP getTSManagerFrameInterval(void *handle);
|
|
||||||
/*!
|
|
||||||
* This function get the current time stamp postion
|
|
||||||
*
|
|
||||||
* @param handle handle of timestamp manager.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
TSM_TIMESTAMP getTSManagerPosition(void *handle);
|
|
||||||
int getTSManagerPreBufferCnt(void *handle);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*_TIMESTAMP_H_ */
|
|
Loading…
Reference in New Issue