/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2020-2020. All rights reserved. * Description: decoder * Author: Hisilicon * Create: 2020-11-11 */ #include "avplay_fc.h" #include #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(); }