PNGD图片解码
本节介绍PNGD图片解码的接口调用流程,同时配合示例代码辅助理解该接口调用流程。
PNGD(PNG decoder)负责PNG格式图片的解码。关于PNGD功能的详细介绍及约束请参见PNGD图片解码功能。

Atlas 200/300/500 推理产品上,当前版本不支持该功能。
Atlas 训练系列产品上,当前版本不支持该功能。
接口调用流程
开发应用时,如果涉及对PNG图片的解码,则应用程序中必须包含解码的代码逻辑,关于图片解码的接口调用流程,请先参见AscendCL接口调用流程了解整体流程,再查看本节中的流程说明。

当前系统支持解码PNG图片,关键接口的说明如下:
- 调用hi_mpi_sys_init接口进行媒体数据处理系统初始化。
- 调用hi_mpi_pngd_create_chn接口创建通道。
- 调用hi_mpi_dvpp_malloc接口申请Device上的内存,存放输入或输出数据。
Atlas 200I/500 A2推理产品上,还支持使用aclrtMalloc接口申请内存。
Atlas A2训练系列产品/Atlas 800I A2推理产品上,还支持使用aclrtMalloc接口申请内存。
调用hi_mpi_dvpp_malloc接口申请的内存为媒体数据处理的专用内存,但专用内存的地址空间有限,若关注内存规划或内存资源有限时,建议调用aclrtMalloc接口申请内存。
- 调用hi_mpi_pngd_send_stream接口发送解码码流,hi_mpi_pngd_send_stream接口是异步接口,调用该接口仅表示任务下发成功,还需要调hi_mpi_pngd_get_image_data接口获取解码结果数据。
- 调用hi_mpi_dvpp_free接口释放输入、输出内存。
Atlas 200I/500 A2推理产品上,若使用aclrtMalloc接口申请内存,则需使用aclrtFree接口释放内存。
Atlas A2训练系列产品/Atlas 800I A2推理产品上,若使用aclrtMalloc接口申请内存,则需使用aclrtFree接口释放内存。
- 调用hi_mpi_pngd_destroy_chn接口销毁通道。
- 调用hi_mpi_sys_exit接口进行媒体数据处理系统去初始化。
示例代码
您可以从样例介绍中获取完整样例代码。
本节中的示例重点介绍PNGD图片解码的代码逻辑,AscendCL初始化和去初始化请参见AscendCL初始化,运行管理资源申请与释放请参见运行管理资源申请与释放。
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
// 1.AscendCL初始化 // 2.运行管理资源申请 // 3.初始化媒体数据处理系统 int32_t ret = hi_mpi_sys_init(); // 4.创建通道 hi_pngd_chn chnId; hi_pngd_chn_attr chnAttr; // hi_pngd_chn_attr都是保留参数,无需设置 ret = hi_mpi_pngd_create_chn(chnId, &chnAttr); // 5.发送码流 // 5.1 申请输入内存 uint8_t* inputAddr = nullptr; // inputsize表示输入图片占用的内存大小,此处以1024 byte为例,用户需根据实际情况计算内存大小 int32_t inputSize = 1024; ret = hi_mpi_dvpp_malloc(0, &inputAddr, inputSize); // 如果运行模式为ACL_HOST,则需要申请Host内存,将输入图片数据读入Host内存,再通过aclrtMemcpy接口将Host的图片数据传输到Device,数据传输完成后,需及时释放Host内存;否则直接将输入图片数据读入Device内存 // runMode表示软件栈的运行模式,可通过aclrtGetRunMode接口获取 if (runMode == ACL_HOST) { void* hostInputAddr = nullptr; // 申请Host内存 aclRet = aclrtMallocHost(&hostInputAddr, inputSize); // 将输入图片读入内存中,该自定义函数ReadStreamFile由用户实现 ReadStreamFile(fileName, hostInputAddr, inputSize); // 数据传输 aclRet = aclrtMemcpy(inputAddr, inputSize, hostInputAddr, inputSize, ACL_MEMCPY_HOST_TO_DEVICE); } else { // 将输入图片读入内存中,该自定义函数ReadStreamFile由用户实现 ReadStreamFile(fileName, inputAddr, inputSize); } // 5.2 构造存放输入图片信息的结构体 hi_img_stream stStream{}; hi_img_info stImgInfo{}; stStream.pts = 0; if (g_runMode == ACL_HOST) { stStream.addr = (uint8_t *)hostInputAddr; } else { stStream.addr = (uint8_t *)inputAddr; } stStream.len = inputSize; stStream.type = HI_PT_PNG; ret = hi_mpi_png_get_image_info(&stStream, &stImgInfo); if (g_runMode == ACL_HOST) { // 如果不使用Host上的数据,需及时释放 aclrtFreeHost(hostInputAddr); hostInputAddr = nullptr; } stStream.addr = (uint8_t *)inputAddr; // 5.3 构造存放输出图片信息的结构体,并申请输出内存 hi_pic_info outPicInfo{}; void *outBuffer = nullptr; outPicInfo.picture_width = stImgInfo.width; outPicInfo.picture_height = stImgInfo.height; outPicInfo.picture_width_stride = stImgInfo.width_stride; outPicInfo.picture_height_stride = stImgInfo.height_stride; outPicInfo.picture_buffer_size = stImgInfo.img_buf_size; outPicInfo.picture_format = HI_PIXEL_FORMAT_UNKNOWN; ret = hi_mpi_dvpp_malloc(0, &outBuffer, outPicInfo.buffer_size); outPicInfo.picture_address = (uint64_t)outBuffer; // 5.4 发送需解码的输入图片 ret = hi_mpi_pngd_send_stream(chnId, &stream, &outPicInfo, 0); // 6.接收解码结果 // 6.1 获取解码结果 hi_pic_info picInfo; hi_img_stream stream; ret = hi_mpi_pngd_get_image_data(chnId, &picInfo, &stream, 0); if (ret == HI_SUCCESS) { // Decode success printf("[%s][%d] Chn %u GetFrame Success, Decode Success \n",__FUNCTION__, __LINE__, chnId); } else if (ret == HI_ERR_PNGD_BUF_EMPTY){ // Decoding printf("[%s][%d] Chn %u Decoding, try again \n",__FUNCTION__, __LINE__, chnId); } else { // Decode fail printf("[%s][%d] Chn %u GetFrame Success, Decode Fail \n",__FUNCTION__, __LINE__, chnId); } // 6.2 如果运行模式为ACL_HOST,且Host上需要展示PNGD输出的图片数据,则需要申请Host内存,通过aclrtMemcpy接口将Device的输出图片数据传输到Host if (g_runMode == ACL_HOST) { void* hostOutputAddr = nullptr; aclRet = aclrtMallocHost(&hostOutputAddr, outputSize); aclRet = aclrtMemcpy(hostOutputAddr, outputSize, frame.v_frame.virt_addr[0], outputSize, ACL_MEMCPY_DEVICE_TO_HOST); // ...... // 数据使用完成后,及时释放不使用的内存 aclrtFreeHost(hostOutputAddr); hostOutputAddr = nullptr; } else { // 可以直接使用PNGD的输出图片数据,在outputPic.picture_address指向的内存中 // ...... } // 6.3 释放输入、输出内存 ret = hi_mpi_dvpp_free(frame.v_frame.virt_addr[0]); ret = hi_mpi_dvpp_free(stream.addr); // 7.销毁通道 ret = hi_mpi_pngd_destroy_chn(chnId); // 8. 媒体数据处理系统去初始化 ret = hi_mpi_sys_exit(); // 9. 释放运行管理资源 // 10.AscendCL去初始化 // .... |