摘要:本期就分享几个关于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. 每个后端都应该了解的OpenResty入门以及网关安全实战

    简介 在官网上对 OpenResty 是这样介绍的(http://openresty.org): "OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成 ...

  2. ida反汇编失败

    options->general->打开堆栈指针(stack pointer) 可见反汇编失败提示的地址(本程序为00101481,原本此处不为000)处堆栈指针不为0,因此需要修改 al ...

  3. Android-Java-反序列化JSON

    import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; String jsonStr= WebAPIOperato ...

  4. windows11配置wsl2虚拟linux环境

    windows11配置wsl2虚拟linux环境 wsl( Windows Subsystem for Linux )是microsoft官方为windows开发的模拟Linux方法.避免了虚拟机vm ...

  5. gametime

    这道题是动态调试的考点,看了wp才有思路 像这样的游戏题一定要搞清楚他的具体游戏流程才能更好的做出来,然后根据他的思路去改掉相关的判断就可以了 攻防世界逆向高手题之gametime_攻防世界 game ...

  6. 2020年第十一届蓝桥杯第二场C/C++ B组省赛题解

    2020年第十一届蓝桥杯C/C++ B组省赛题解 试题A:门牌制作 [问题描述] 小蓝要为一条街的住户制作门牌号. 这条街一共有 \(2020\) 位住户,门牌号从 \(1\) 到 \(2020\) ...

  7. python之封装及私有方法

    目录 封装 简洁 私有方法 封装:提高程序的安全性 将属性和方法包装到类对象中,在方法内部对属性进行操作,在类对象外部调用方法,使得程序更加简洁 在python中,如果该属性不希望在类对象外部被访问, ...

  8. 纯css步骤条编写

    .steps { position: relative; margin-bottom: 30px; counter-reset: step; /*创建步骤数字计数器*/ } /*步骤描述*/ .ste ...

  9. 在路上---学习篇(一)Python 数据结构和算法 (4) --希尔排序、归并排序

    独白: 希尔排序是经过优化的插入排序算法,之前所学的排序在空间上都是使用列表本身.而归并排序是利用增加新的空间,来换取时间复杂度的减少.这俩者理念完全不一样,注定造成的所消耗的时间不同以及空间上的不同 ...

  10. OPC 协议数据采集

    kepserver   OPC Connectivity Suite 让系统和应用程序工程师能够从单一应用程序中管理他们的 OPC 数据访问 (DA) 和 OPC 统一架构 (UA) 服务器.通过减少 ...