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.

385 lines
12 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2020-2020. All rights reserved.
* Description: decoder
* Author: Hisilicon
* Create: 2020-11-11
*/
#include "avplay_fc.h"
#include <sys/prctl.h>
#include "dft_event.h"
#include "avplay_common.h"
#define AVPLAY_FC_ERROR_ID 955291001
#define AVPLAY_FC_ID_VDEC_SPEED_ERR 20
#define AVPLAY_FC_ID_ADEC_SPEED_ERR 21
#define AVPLAY_FC_ID_EOS_FAIL 22
#define AVPLAY_FC_ID_PTS_NORMAL_LOOP_ERR 23
#define AVPLAY_FC_EOS_CHECK_TIMEOUT 20000
volatile td_bool g_adec_speed_inject = TD_FALSE;
__attribute__((optnone)) void adec_speed_inject_fault()
{
g_adec_speed_inject = TD_TRUE;
ext_info_avplay("g_adec_speed_inject:%d\n", g_adec_speed_inject);
}
__attribute__((optnone)) void adec_speed_uninject_fault()
{
g_adec_speed_inject = TD_FALSE;
ext_info_avplay("g_adec_speed_inject:%d\n", g_adec_speed_inject);
}
volatile td_bool g_vdec_speed_inject = TD_FALSE;
__attribute__((optnone)) void vdec_speed_inject_fault()
{
g_vdec_speed_inject = TD_TRUE;
ext_info_avplay("g_vdec_speed_inject:%d\n", g_vdec_speed_inject);
}
__attribute__((optnone)) void vdec_speed_uninject_fault()
{
g_vdec_speed_inject = TD_FALSE;
ext_info_avplay("g_vdec_speed_inject:%d\n", g_vdec_speed_inject);
}
volatile td_bool g_eos_fail_inject = TD_FALSE;
__attribute__((optnone)) void eos_fail_inject_fault()
{
g_eos_fail_inject = TD_TRUE;
ext_info_avplay("g_eos_fail_inject:%d\n", g_eos_fail_inject);
}
__attribute__((optnone)) void eos_fail_uninject_fault()
{
g_eos_fail_inject = TD_FALSE;
ext_info_avplay("g_eos_fail_inject:%d\n", g_eos_fail_inject);
}
volatile td_bool g_pts_normal_loop_err_inject = TD_FALSE;
__attribute__((optnone)) void pts_normal_loop_err_inject()
{
g_pts_normal_loop_err_inject = TD_TRUE;
ext_info_avplay("g_pts_normal_loop_err_inject:%d\n", g_pts_normal_loop_err_inject);
}
__attribute__((optnone)) void pts_normal_loop_err_uninject()
{
g_pts_normal_loop_err_inject = TD_FALSE;
ext_info_avplay("g_pts_normal_loop_err_inject:%d\n", g_pts_normal_loop_err_inject);
}
typedef struct {
td_char *tag_name;
td_char *tag_info;
} fc_tag_info;
typedef struct {
td_u32 index;
td_u32 err_id;
fc_tag_info f1_info;
fc_tag_info f2_info;
fc_tag_info detail_info;
} avplay_fc_err_info;
static avplay_fc_err_info g_avplay_fc_err_table[] = {
{
.index = AVPLAY_FC_ID_VDEC_SPEED_ERR,
.err_id = AVPLAY_FC_ERROR_ID,
.f1_info = {
.tag_name = "F1NAME",
.tag_info = "avplay"
},
.f2_info = {
.tag_name = "F2NAME",
.tag_info = "avplay vdec speed error"
},
.detail_info = {
.tag_name = "VDEC_SPEED_ERR",
.tag_info = "1"
},
},
{
.index = AVPLAY_FC_ID_ADEC_SPEED_ERR,
.err_id = AVPLAY_FC_ERROR_ID,
.f1_info = {
.tag_name = "F1NAME",
.tag_info = "avplay"
},
.f2_info = {
.tag_name = "F2NAME",
.tag_info = "avplay adec speed error"
},
.detail_info = {
.tag_name = "ADEC_SPEED_ERR",
.tag_info = "1"
},
},
{
.index = AVPLAY_FC_ID_EOS_FAIL,
.err_id = AVPLAY_FC_ERROR_ID,
.f1_info = {
.tag_name = "F1NAME",
.tag_info = "avplay"
},
.f2_info = {
.tag_name = "F2NAME",
.tag_info = "avplay eos error"
},
.detail_info = {
.tag_name = "EOS_ERR",
.tag_info = "1"
},
},
{
.index = AVPLAY_FC_ID_PTS_NORMAL_LOOP_ERR,
.err_id = AVPLAY_FC_ERROR_ID,
.f1_info = {
.tag_name = "F1NAME",
.tag_info = "avplay"
},
.f2_info = {
.tag_name = "F2NAME",
.tag_info = "avplay pts normal loop err"
},
.detail_info = {
.tag_name = "PTS_NORMAL_LOOP_ERR",
.tag_info = "1"
},
},
};
static avplay_fc_err_info *avplay_get_err_info(td_u32 index)
{
td_u32 i;
size_t num = sizeof(g_avplay_fc_err_table) / sizeof(avplay_fc_err_info);
for (i = 0; i < num; i++) {
if (g_avplay_fc_err_table[i].index == index) {
return &g_avplay_fc_err_table[i];
}
}
return TD_NULL;
}
static td_void fc_report_err_event(td_u32 index)
{
td_s32 ret;
td_handle handle;
td_char name[1024] = {0};
avplay_fc_err_info *err_info = avplay_get_err_info(index);
if (err_info == TD_NULL) {
ext_err_avplay("no such err index:%d\n", index);
return;
}
ret = (td_s32)dft_event_create(err_info->err_id, &handle);
if (ret == TD_SUCCESS) {
prctl(PR_GET_NAME, name);
dft_event_put_string(handle, "PNAME", name);
dft_event_put_string(handle, err_info->f1_info.tag_name, err_info->f1_info.tag_info);
dft_event_put_string(handle, err_info->f2_info.tag_name, err_info->f2_info.tag_info);
dft_event_put_string(handle, err_info->detail_info.tag_name, err_info->detail_info.tag_info);
dft_event_report(handle);
dft_event_destroy(handle);
}
ext_info_avplay("err_id: %d\n PNAME: %s\n %s: %s\n %s: %s\n %s: %s\n",
err_info->err_id, name,
err_info->f1_info.tag_name, err_info->f1_info.tag_info,
err_info->f2_info.tag_name, err_info->f2_info.tag_info,
err_info->detail_info.tag_name, err_info->detail_info.tag_info);
return;
}
td_void avplay_fault_check_init(avplay_context *ctx)
{
if (ctx == NULL) {
ext_err_avplay("%s, ctx is null.", __FUNCTION__);
return;
}
ctx->fc_info.is_adec_speed_err_report = TD_FALSE;
ctx->fc_info.is_vdec_speed_err_report = TD_FALSE;
ctx->fc_info.is_pts_normal_loop_err_report = TD_FALSE;
ctx->fc_info.is_eos_fail_err_report = TD_FALSE;
ctx->fc_info.aud_eos_report_check_status = TD_FALSE;
ctx->fc_info.vid_eos_report_check_status = TD_FALSE;
ctx->fc_info.aud_eos_report_check_start_time = 0;
ctx->fc_info.vid_eos_report_check_start_time = 0;
}
td_void avplay_fault_check_deinit(avplay_context *ctx)
{
if (ctx == NULL) {
ext_err_avplay("%s, ctx is null.", __FUNCTION__);
return;
}
ctx->fc_info.is_adec_speed_err_report = TD_FALSE;
ctx->fc_info.is_vdec_speed_err_report = TD_FALSE;
ctx->fc_info.is_pts_normal_loop_err_report = TD_FALSE;
ctx->fc_info.is_eos_fail_err_report = TD_FALSE;
ctx->fc_info.aud_eos_report_check_status = TD_FALSE;
ctx->fc_info.vid_eos_report_check_status = TD_FALSE;
ctx->fc_info.aud_eos_report_check_start_time = 0;
ctx->fc_info.vid_eos_report_check_start_time = 0;
}
static td_void avplay_fc_adec_speed_err_check()
{
td_bool inject = avplay_get_inject_value(AVPLAY_FC_ID_ADEC_SPEED_ERR);
if (inject == TD_TRUE) {
fc_report_err_event(AVPLAY_FC_ID_ADEC_SPEED_ERR);
g_adec_speed_inject = TD_FALSE;
return;
}
}
/**
* @brief adec speed check.
*/
static td_void avplay_fault_check_adec_speed_process()
{
avplay_fc_adec_speed_err_check();
}
static td_void avplay_fc_vdec_speed_err_check()
{
td_bool inject = avplay_get_inject_value(AVPLAY_FC_ID_VDEC_SPEED_ERR);
if (inject == TD_TRUE) {
fc_report_err_event(AVPLAY_FC_ID_VDEC_SPEED_ERR);
g_vdec_speed_inject = TD_FALSE;
}
}
/**
* @brief vdec speed check.
*/
static td_void avplay_fault_check_vdec_speed_process()
{
avplay_fc_vdec_speed_err_check();
}
static td_bool is_need_report_eos_fail_err(avplay_context *ctx)
{
// video eos report check
if (ctx->vid.enable && ctx->fc_info.is_eos_fail_err_report == TD_FALSE &&
ctx->vid.set_eos_flag == TD_TRUE && ctx->vid.used_buf_percent == 0) {
if (ctx->fc_info.vid_eos_report_check_status == TD_FALSE) {
ctx->fc_info.vid_eos_report_check_start_time = avplay_gettime_system();
ctx->fc_info.vid_eos_report_check_status = TD_TRUE;
ext_info_avplay("vdec eos vid_eos_report_check_status start.");
}
if (ctx->fc_info.vid_eos_report_check_status == TD_TRUE &&
(avplay_gettime_system() - ctx->fc_info.vid_eos_report_check_start_time > AVPLAY_FC_EOS_CHECK_TIMEOUT) &&
(ctx->vid.vdec_eos == TD_FALSE || ctx->vid.eos_reported == TD_FALSE)) {
ctx->fc_info.is_eos_fail_err_report = TD_TRUE;
ext_info_avplay("%s, vdec eos not report, report event.", __FUNCTION__);
return TD_FALSE;
}
}
// audio eos report check
if (ctx->aud.enable && ctx->fc_info.is_eos_fail_err_report == TD_FALSE &&
ctx->aud.set_eos_flag == TD_TRUE && ctx->aud.used_buf_percent == 0) {
if (ctx->fc_info.aud_eos_report_check_status == TD_FALSE) {
ctx->fc_info.aud_eos_report_check_start_time = avplay_gettime_system();
ctx->fc_info.aud_eos_report_check_status = TD_TRUE;
ext_info_avplay("adec eos aud_eos_report_check_status start.");
}
if (ctx->fc_info.aud_eos_report_check_status == TD_TRUE &&
(avplay_gettime_system() - ctx->fc_info.aud_eos_report_check_start_time > AVPLAY_FC_EOS_CHECK_TIMEOUT) &&
(ctx->aud.adec_eos == TD_FALSE || ctx->aud.eos_reported == TD_FALSE)) {
ctx->fc_info.is_eos_fail_err_report = TD_TRUE;
ext_info_avplay("%s, adec eos not report, report event.", __FUNCTION__);
return TD_FALSE;
}
}
return TD_FALSE;
}
static td_void avplay_fc_eos_fail_check(avplay_context *ctx)
{
td_bool inject = avplay_get_inject_value(AVPLAY_FC_ID_EOS_FAIL);
if (inject == TD_TRUE) {
fc_report_err_event(AVPLAY_FC_ID_EOS_FAIL);
g_eos_fail_inject = TD_FALSE;
ext_info_avplay("%s, eos test report, report event.", __FUNCTION__);
return;
}
if (ctx->com.cur_state != UAPI_AVPLAY_STATUS_PLAY ||
ctx->fc_info.is_eos_fail_err_report == TD_TRUE) {
return;
}
if (is_need_report_eos_fail_err(ctx)) {
fc_report_err_event(AVPLAY_FC_ID_EOS_FAIL);
return;
}
}
/**
* @brief eos check.
*/
static td_void avplay_fault_check_eos_fail_process(avplay_loop *loop)
{
avplay_context *ctx = loop->ctx;
avplay_fc_eos_fail_check(ctx);
}
static td_void avplay_fc_pts_normal_loop_err_check()
{
td_bool inject = avplay_get_inject_value(AVPLAY_FC_ID_PTS_NORMAL_LOOP_ERR);
if (inject == TD_TRUE) {
fc_report_err_event(AVPLAY_FC_ID_PTS_NORMAL_LOOP_ERR);
g_pts_normal_loop_err_inject = TD_FALSE;
ext_info_avplay("%s, pts normal loop err test report, report event.", __FUNCTION__);
return;
}
}
static td_void avplay_fault_check_pts_normal_loop_err_process()
{
avplay_fc_pts_normal_loop_err_check();
}
td_bool avplay_get_inject_value(td_u32 event_id)
{
switch (event_id) {
case AVPLAY_FC_ID_VDEC_SPEED_ERR:
return g_vdec_speed_inject;
case AVPLAY_FC_ID_ADEC_SPEED_ERR:
return g_adec_speed_inject;
case AVPLAY_FC_ID_EOS_FAIL:
return g_eos_fail_inject;
case AVPLAY_FC_ID_PTS_NORMAL_LOOP_ERR:
return g_pts_normal_loop_err_inject;
default:
ext_err_avplay("%s, event is is invalidated event_id:%d.", __FUNCTION__, event_id);
return TD_FALSE;
}
}
td_void avplay_fault_check_process(avplay_loop *loop)
{
if (loop == NULL) {
ext_err_avplay("%s, loop is null.", __FUNCTION__);
return;
}
avplay_fault_check_adec_speed_process();
avplay_fault_check_vdec_speed_process();
avplay_fault_check_eos_fail_process(loop);
avplay_fault_check_pts_normal_loop_err_process();
}