摘要:本期就分享几个关于DVPP视频解码问题的典型案例,并给出原因分析及解决方法

本文分享自华为云社区《DVPP媒体数据处理视频解码问题案例》,作者:昇腾CANN 。

DVPP(Digital Vision Pre-Processing)是昇腾AI处理器内置的图像处理单元,通过AscendCL媒体数据处理接口提供强大的媒体处理硬加速能力,主要功能包括图像编解码、视频编解码、图像抠图缩放等。

本期就分享几个关于DVPP视频解码问题的典型案例,并给出原因分析及解决方法:

  1. 视频解码进程卡死,无法退出
  2. retCode返回值设置错误,导致视频解码异常
  3. 视频解码无报错,但无解码结果数据,且CPU占用率高

01 视频解码进程卡死,无法退出

现象描述

用户进程卡死,无法退出。查看应用类日志,一直重复提示信息“fault kernel_name=DvppSendVdecFrame”、“Kernel task happen error, retCode=0x28, [aicpu timeout]”,表示AI CPU异常,无法处理视频解码任务,导致任务超时。

日志片段举例如下:

[ERROR] RUNTIME(pid,pName):DateTimeMS [task.cc:878]1827 PreCheckTaskErr:[DVPP][DEFAULT]Kernel task happen error, retCode=0x28, [aicpu timeout].
[ERROR] RUNTIME(pid,pName):DateTimeMS [task.cc:676]1827 PrintAicpuErrorInfo:[DVPP][DEFAULT]Aicpu kernel execute failed, device_id=0, stream_id=177, task_id=4, fault so_name=libdvpp_kernels.so, fault kernel_name=DvppSendVdecFrame, fault op_name=, extend_info=.
[ERROR] RUNTIME(pid,pName):DateTimeMS [task.cc:878]1831 PreCheckTaskErr:[DVPP][DEFAULT]Kernel task happen error, retCode=0x28, [aicpu timeout].
[ERROR] RUNTIME(pid,pName):DateTimeMS [task.cc:676]1831 PrintAicpuErrorInfo:[DVPP][DEFAULT]Aicpu kernel execute failed, device_id=0, stream_id=170, task_id=8, fault so_name=libdvpp_kernels.so, fault kernel_name=DvppSendVdecFrame, fault op_name=, extend_info=.
[ERROR] RUNTIME(pid,pName):DateTimeMS [engine.cc:960]1766 ReportExceptProc:[DVPP][DEFAULT]Task exception! device_id=0, stream_id=107, task_id=8, type=1, retCode=0x28.
[ERROR] RUNTIME(pid,pName):DateTimeMS [engine.cc:960]1773 ReportExceptProc:[DVPP][DEFAULT]Task exception! device_id=0, stream_id=130, task_id=4, type=1, retCode=0x28.

可能原因

Device内存不足,AI CPU无法处理视频解码任务,导致任务超时。

处理步骤

1.在使用媒体数据处理V1版本的视频解码功能前,可参考性能指标说明页面中的“每路VDEC解码的内存消耗计算公式”,预估需使用的Device内存,并合理规划Device上的内存。
您可以在页面左上侧切换版本,查看对应版本的性能指标说明。

2.优化应用程序的代码逻辑,增加异常处理机制,获取视频解码异常信息,强制退出进程。

在调用aclinit接口初始化之后、调用aclvdecSendFrame接口解码之前,定义异常回调函数,并调用aclrtSetExceptionInfoCallback接口设置异常回调函数,用于获取任务异常信息,以便在异常分支中根据任务异常信息来判断是否退出应用进程。

  • 定义异常回调函数,回调函数原型为:typedef void (*aclrtExceptionInfoCallback)(aclrtExceptionInfo *exceptionInfo)
  • 实现异常回调函数,在异常回调函数fn内调用aclrtGetDeviceIdFromExceptionInfo、aclrtGetStreamIdFromExceptionInfo、aclrtGetTaskIdFromExceptionInfo接口分别获取Device ID、Stream ID、Task ID。

根据Stream ID、Task ID判断Device是否异常,若异常,则强制退出进程。

异常回调函数实现示例如下:

void dvpp_callback(aclrtExceptionInfo * exception_info)
{
uint32_t taskId = aclrtGetTaskIdFromExceptionInfo(exception_info);
uint32_t streamId = aclrtGetStreamIdFromExceptionInfo(exception_info);
uint32_t deviceId = aclrtGetDeviceIdFromExceptionInfo(exception_info);
if(taskId == 0xffffffff) || (streamId == 0xffffffff) {
//Device异常,强制退出进程
} else {
//任务异常,如果频繁出现(例如,统计1秒内触发异常回调函数的次数),进程退出
}
return;
}

3.调用aclrtSetExceptionInfoCallback接口设置异常回调函数。

02 retCode返回值设置错误,导致视频解码异常

现象描述

调用aclvdecSendFrame接口发送一帧码流后,继续复用输出图片描述信息,进行后续帧码流的解码操作,结果反复出现解码不成功、解码异常的情况。

日志片段举例如下:

Channel[0]: success to aclvdecSendFrame, loop=1, count=7
get frame success, totalCount=7
packet.size is 26084.
Channel[0]: begin to send frame, loop=1, count=8
acldvppGetPicDescRetCode, retCode: 2.
Vdec ERROR!!!!!!!!!!!!!!!!
errCount is 3. total count is 3.
!!!!!!!!!!!!!!!!!!acldvppGetPicDescRetCode, retCode: 2.right_count:0,fail_count:3,total_count:3
Channel[0]: success to aclvdecSendFrame, loop=1, count=8
get frame success, totalCount=8
packet.size is 27927.
Channel[0]: begin to send frame, loop=1, count=9
acldvppGetPicDescRetCode, retCode: 2.
Vdec ERROR!!!!!!!!!!!!!!!!
errCount is 4. total count is 4.
!!!!!!!!!!!!!!!!!!acldvppGetPicDescRetCode, retCode: 2.right_count:0,fail_count:4,total_count:4

可能原因

根据日志中的提示,通过acldvppGetPicDescRetCode接口获取到的retCode为2,retCode为非0值时,表示解码异常。

再查看代码逻辑时,发现由于前一帧码流解码失败,retCode被置为2,在复用输出图片描述信息时,retCode也继承了前一帧解码失败的状态值2,导致AscendCL在解码后续帧时,获取到retCode值为2,就一直判断解码是失败。

处理步骤

如果存在复用输出图片描述信息的场景,需先调用acldvppSetPicDescRetCode设置为0,防止前一帧解码异常的状态影响后续解码。

03 视频解码无报错,但无解码结果数据、CPU占用率高

现象描述

查看应用类日志,无ERROR报错、无解码结果数据输出,另外,在运行应用程序的Linux服务器上执行top命令,该应用进程的CPU占用率持续升高。

可能原因

1. 无ERROR、无解码结果数据输出,初步判断可能是因为解码发帧接口aclvdecSendFrame调用正常,但未触发回调函数,无法获取解码结果数据。

2. 检查触发回调函数的代码逻辑。

按照视频解码的接口调用逻辑:由用户提前创建一个单独的线程,并自定义线程函数,在线程函数内调用aclrtProcessReport接口,通过该接口配置超时时间,等待指定的超时时间后,触发回调函数,获取解码结果数据。

Channel[0]: success to aclvdecSendFrame, loop=1, count=7
get frame success, totalCount=7
void *ThreadFunc(aclrtContext sharedContext)
{
if (sharedContext == nullptr) {
ERROR_LOG("sharedContext can not be nullptr");
return ((void*)(-1));
}
INFO_LOG("use shared context for this thread");
aclError ret = aclrtSetCurrentContext(sharedContext);
if (ret != ACL_SUCCESS) {
ERROR_LOG("aclrtSetCurrentContext failed, errorCode = %d", static_cast<int32_t>(ret));
return ((void*)(-1));
}
INFO_LOG("thread start ");
while (runFlag) {
// Notice: timeout 1000ms
(void)aclrtProcessReport(1000);
}
return (void*)0;
}

3. 如果触发回调函数的接口调用逻辑正确,则在aclrtProcessReport接口处增加日志打印,判断应用运行过程中线程是否成功调用了aclrtProcessReport接口,只有成功调用aclrtProcessReport接口,才会触发回调函数。

示例代码如下:

while (runFlag) {
// Notice: timeout 1000ms
aclError ret = aclrtProcessReport(1000);
printf("aclrtProcessReport failed, ret=%d.\n", ret);
}

4. 修改代码后,重新编译运行应用。

在终端屏幕重复出现以下打印信息,表示调用aclrtProcessReport接口失败:

aclrtProcessReport failed, ret = 107012

查阅该接口的返回值说明,107012表示线程未订阅或重复订阅。

5. 检查代码逻辑,检查是否调用aclvdecSetChannelDescThreadId接口绑定用户新建的线程,按照VDEC视频解码的接口调用逻辑,只有调用该接口绑定用户线程,才可以触发调用aclrtProcessReport接口,进而触发回调函数。

6. 修改代码后,重新编译运行应用,视频解码正常,正常输出解码结果数据,同时CPU占用率下降。

处理步骤

参见视频解码的接口调用流程页面或者参考VDEC功能样例开发视频解码功能。您可以在页面左上侧切换版本,查看对应版本的接口调用流程。

其中,需关注以下注意点:

  • 创建新线程,并自定义线程函数,在线程函数内调用aclrtProcessReport接口,等待指定时间后,触发回调函数中的回调函数。
  • 需调用aclvdecSetChannelDescThreadId接口绑定用户创建的新线程。
  • 释放资源时,依次销毁通道、销毁通道描述信息后,才可以销毁中用户创建的新线程。

04 更多介绍

[1]昇腾文档中心

[2]昇腾社区在线课程

[3]昇腾论坛

点击关注,第一时间了解华为云新鲜技术~

昇腾实战丨DVPP媒体数据处理视频解码问题案例的更多相关文章

  1. hadoop大数据处理平台与案例

    大数据可以说是从搜索引擎诞生之处就有了,我们熟悉的搜索引擎,如百度搜索引擎.360搜索引擎等可以说是大数据技处理技术的最早的也是比较基础的一种应用.大概在2015年大数据都还不是非常火爆,2015年可 ...

  2. 大数据开发实战:离线大数据处理的主要技术--Hive,概念,SQL,Hive数据库

    1.Hive出现背景 Hive是Facebook开发并贡献给Hadoop开源社区的.它是建立在Hadoop体系架构上的一层SQL抽象,使得数据相关人员使用他们最为熟悉的SQL语言就可以进行海量数据的处 ...

  3. python实战——文本挖掘+xgboost预测+数据处理+准确度计算整合版

    if __name__=="__main__": '''============================先导入数据============================= ...

  4. 实战丨快速搭建实时 Todo List 应用

    技术背景 借助云开发数据库的实时推送能力和云开发官方出品的前后端一体化部署工具CloudBase Framework,可以轻松搭建一个完整应用. 效果展示 示例地址:http://cloud.qinm ...

  5. 【h5+c3】web前端实战项目、快装webapp手机案例源码

    快装WebApp项目(Web移动端开发案例)webapp移动端项目源码.html5+css3实战案例分享.微信端H5实例开发 简介快装WebApp是一个面向移动端的快速装修app,此项目为手机端:使用 ...

  6. Redis秒杀实战-微信抢红包-秒杀库存,附案例源码(Jmeter压测)

    导读 前二天我写了一篇,Redis高级项目实战(点我直达),SpringBoot整合Redis附源码(点我直达),今天我们来做一下Redis秒杀系统的设计.当然啦,Redis基础知识还不过关的,先去加 ...

  7. [.NET领域驱动设计实战系列]专题七:DDD实践案例:引入事件驱动与中间件机制来实现后台管理功能

    一.引言 在当前的电子商务平台中,用户下完订单之后,然后店家会在后台看到客户下的订单,然后店家可以对客户的订单进行发货操作.此时客户会在自己的订单状态看到店家已经发货.从上面的业务逻辑可以看出,当用户 ...

  8. [.NET领域驱动设计实战系列]专题六:DDD实践案例:网上书店订单功能的实现

    一.引言 上一专题已经为网上书店实现了购物车的功能了,在这一专题中,将继续对网上书店案例进行完善,本专题将对网上书店订单功能的实现进行介绍,现在废话不多说了,让我们来一起看看订单功能是如何实现的吧. ...

  9. JavaScript使用DeviceOne开发实战(六)点墨真实案例

    qq群里的yan用户开发的App,基本完工大家可以看看 安装二维码是 QQ群:365443130

  10. Pandas数据处理+Matplotlib绘图案例

    利用pandas对数据进行预处理然后再使用matplotlib对处理后的数据进行数据可视化是数据分析中常用的方法. 第一组例子(星巴克咖啡店) 假如我们现在有这样一组数据:星巴克在全球的咖啡店信息,如 ...

随机推荐

  1. Java 深度优先搜索 and 广度优先搜索的算法原理和代码展示

    111. 二叉树的最小深度 题目:给定一个二叉树,找出其最小深度.最小深度是从根节点到最近叶子节点的最短路径上的节点数量. 说明:叶子节点是指没有子节点的节点. 方法1:深度优先搜索 原理:深度优先搜 ...

  2. CDQ分治和三维偏序

    专题:CDQ 分治 本页面将完整介绍 CDQ 分治. 简介 CDQ 分治是一种思想而不是具体的算法,与动态规划类似.目前这个思想的拓展十分广泛,依原理与写法的不同,大致分为三类: 解决和点对有关的问题 ...

  3. CSP 2023 游记

    省流:把 #define int long long 写在快读下面,找到答案了不 break. Day -1 手速大赛很有趣,但有人不认识 Aigony 我不说是谁. Day 0 睡大觉,给小朋友讲考 ...

  4. JAVA多线程(1)——线程

    1.定义:线程是一个程序里面不同的执行路径   例子1:只有一个执行路径 (一个分支,即主线程)

  5. Acwing127周赛第三题 构造矩阵 (套路)

    题目链接:构造矩阵 题目描述 我们希望构造一个 n×m 的整数矩阵. 构造出的矩阵需满足: 每一行上的所有元素之积均等于 k. 每一列上的所有元素之积均等于 k. 保证 k 为 1 或 −1. 请你计 ...

  6. .NET快速对接极光消息推送

    什么是消息推送? 很多手机APP会不定时的给用户推送消息,例如一些新闻APP会给用户推送用户可能感兴趣的新闻,或者APP有更新了,会给用户推送是否选择更新的消息等等,这就是所谓的"消息推送& ...

  7. 在 Ubuntu 22.04 系统上为 SSH 开启基于时间的 TOTP 认证

    前言 一次性密码(英语:one-time password,简称OTP),又称动态密码或单次有效密码,是指电脑系统或其他数字设备上只能使用一次的密码,有效期为只有一次登录会话或一段短时间内.基于时间的 ...

  8. python列表之索引及len()函数

    我们在刚开始使用列表的时候,经常会遇到这种错误 list_1 = ['one', 'two', 'three', 'four', 'five'] print(list_1[5]) 这段代码看上去是没有 ...

  9. 【Android】无法通过drawable下的selector类型改变背景颜色?

    举例 我在darwable目录下创建了selector文件,并设置了如下内容 <?xml version="1.0" encoding="utf-8"?& ...

  10. Tomcat 配合虚拟线程,一种新的编程体验

    Java 21 在今年早些时候的 9 月 19 日就正式发布,并开始正式引入虚拟线程,但是作为 Java 开发生态中老大哥 Spring 并没有立即跟进,而是在等待了两个月后的 11 月 29 日,伴 ...