昇腾实战丨DVPP媒体数据处理视频解码问题案例

实战,dvpp,媒体,数据处理,视频,解码,问题,案例 · 浏览次数 : 26

小编点评

# 华为云新鲜技术视频解码无报错 # 1. 无ERROR、无解码结果数据输出 * 应用程序进程的日志显示无ERROR或解码结果数据输出。 * 在top命令中,没有发现任何异常或解码结果数据。 # 2. 检查触发回调函数的代码逻辑 * 应用程序代码中使用了aclrtProcessReport接口来触发回调函数。 * 回调函数的代码逻辑中检查了线程是否成功调用了aclrtProcessReport接口。 # 3. 代码修改后,重新编译运行应用 * 修改代码后,重新编译运行应用程序。 * 应用正常,视频解码正常,正常输出解码结果数据。 # 4. 修改代码后,重新编译运行应用 * 修改代码后,重新编译运行应用程序。 * 应用正常,视频解码正常,正常输出解码结果数据。 # 5. 检查代码逻辑,检查是否调用aclvdecSetChannelDescThreadId接口绑定用户创建的新线程 * 代码中使用了aclvdecSetChannelDescThreadId接口绑定用户创建的新线程。 * 确保线程绑定成功后,才能调用该接口绑定用户创建的新线程。 # 6. 代码修改后,重新编译运行应用 * 修改代码后,重新编译运行应用程序。 * 应用正常,视频解码正常,正常输出解码结果数据。 # 7. 更多介绍 * **[1]昇腾文档中心** * **[2]昇腾社区在线课程** * **[3]昇腾论坛 点击关注,第一时间了解华为云新鲜技术~**

正文

摘要:本期就分享几个关于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媒体数据处理视频解码问题案例相似的内容:

昇腾实战丨DVPP媒体数据处理视频解码问题案例

摘要:本期就分享几个关于DVPP视频解码问题的典型案例,并给出原因分析及解决方法 本文分享自华为云社区《DVPP媒体数据处理视频解码问题案例》,作者:昇腾CANN 。 DVPP(Digital Vision Pre-Processing)是昇腾AI处理器内置的图像处理单元,通过AscendCL媒体数

昇腾实战丨DVPP媒体数据处理图片解码问题案例

摘要:本期就分享几个关于DVPP图片解码问题的典型案例,并给出原因分析及解决方法。 本文分享自华为云社区《DVPP媒体数据处理图片解码问题案例》,作者:昇腾CANN 。 DVPP(Digital Vision Pre-Processing)是昇腾AI处理器内置的图像处理单元,通过AscendCL媒体

昇腾实践丨ATC模型转换动态shape问题案例

本期就分享几个关于昇腾CANN中关于ATC模型转换动态shape相关问题的典型案例,并给出原因分析及解决方法。

AI推理实践丨多路极致性能目标检测最佳实践设计解密

摘要:基于CANN的多路极致性能目标检测最佳实践设计解密。 本文分享自华为云社区《基于CANN的AI推理最佳实践丨多路极致性能目标检测应用设计解密》,作者: 昇腾CANN 。 当前人工智能领域,最热门的无疑是以ChatGPT为代表的各种“新贵”大模型,它们高高在上,让你无法触及。但在人们的日常生活中

盘它!基于CANN的辅助驾驶AI实战案例,轻松搞定车辆检测和车距计算!

摘要:基于昇腾AI异构计算架构CANN(Compute Architecture for Neural Networks)的简易版辅助驾驶AI应用,具备车辆检测、车距计算等基本功能,作为辅助驾驶入门级项目再合适不过。 本文分享自华为云社区《盘它!基于CANN的辅助驾驶AI实战案例,轻松搞定车辆检测和

昇腾携手OpenMMLab,支持海量算法仓库的昇腾AI推理部署

摘要:近日,昇腾AI联合上海人工智能实验室,正式实现OpenMMLab算法仓库在昇腾的异构计算架构CANN上的推理部署,目前相关代码已推入MMDeploy 0.10.0版本,并在GitHub正式发布。 本文分享自华为云社区《昇腾携手OpenMMLab,支持海量算法仓库的昇腾AI推理部署》,作者:昇腾

理论+实践,揭秘昇腾CANN算子开发

摘要: 本文介绍了CANN自定义算子开发的几种开发方式和算子的编译运行流程。然后以开发一个DSL Add算子为例,讲解算子开发的基本流程。 本文分享自华为云社区《昇腾CANN算子开发揭秘》,作者:昇腾CANN 。 开发者在利用昇腾硬件进行神经网络模型训练或者推理的过程中,可能会遇到以下场景: 训练场

三步实现BERT模型迁移部署到昇腾

本文从镜像构建、容器部署到性能评估,完成bert模型昇腾迁移部署案例。

基于昇腾计算语言AscendCL开发AI推理应用

摘要:本文介绍了昇腾计算语言AscendCL的基本概念,并以示例代码的形式介绍了如何基于AscendCL开发AI推理应用,最后配以实际的操作演示说明如何编译运行应用。 本文分享自华为云社区《基于昇腾计算语言AscendCL开发AI推理应用》,作者:昇腾CANN。 初始AscendCL AscendC

手把手教你在昇腾平台上搭建PyTorch训练环境

摘要:在昇腾平台上运行PyTorch业务时,需要搭建异构计算架构CANN软件开发环境,并安装PyTorch 框架,从而实现训练脚本的迁移、开发和调试。 本文分享自华为云社区《手把手教你在昇腾平台上搭建PyTorch训练环境》,作者:昇腾CANN。 PyTorch是业界流行的深度学习框架,用于开发深度