缩放

基本原理

示例代码

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。

// 1.AscendCL初始化
aclRet = aclInit(nullptr);

// 2.运行管理资源申请(依次申请Device、Context)
aclrtContext g_context;
aclRet = aclrtSetDevice(0);
aclRet = aclrtCreateContext(&g_context, 0);
// 获取软件栈的运行模式,不同运行模式影响后续的接口调用流程(例如是否进行数据传输等)
aclrtRunMode runMode;
aclError aclRet = aclrtGetRunMode(&runMode);

// 3.初始化媒体数据处理系统
int32_t ret = hi_mpi_sys_init();

// 4.创建通道
hi_vpc_chn chnId;
hi_vpc_chn_attr stChnAttr;
ret = hi_mpi_vpc_sys_create_chn(&chnId, &stChnAttr);

// 5.执行缩放
// 5.1 构造存放输入图片信息的结构体
hi_vpc_pic_info inputPic;
inputPic.picture_width = 1920;
inputPic.picture_height = 1080;
inputPic.picture_format = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
inputPic.picture_width_stride = 1920;
inputPic.picture_height_stride = 1080;
inputPic.picture_buffer_size = inputPic.picture_width_stride * inputPic.picture_height_stride * 3 / 2;

// 5.2 准备输入图片数据
// 申请Device内存,用于媒体数据处理
ret = hi_mpi_dvpp_malloc(0, &inputPic.picture_address, inputPic.picture_buffer_size);

// 如果运行模式为ACL_HOST,则需要申请Host内存,将输入图片数据读入Host内存,再通过aclrtMemcpy接口将Host的图片数据传输到Device,数据传输完成后,需及时释放Host内存;否则直接将输入图片数据读入Device内存
if (runMode == ACL_HOST) {
    void* inputAddr = nullptr;
    // 申请Host内存
    aclRet = aclrtMallocHost(&inputAddr, inputPic.picture_buffer_size);
    // 将输入图片读入内存中,该自定义函数ReadPicFile由用户实现
    ReadPicFile(picName, inputAddr, inputPic.picture_buffer_size);
    // 数据传输
    aclRet = aclrtMemcpy(inputPic.picture_address, inputPic.picture_buffer_size, inputAddr,
                         inputPic.picture_buffer_size, ACL_MEMCPY_HOST_TO_DEVICE);
    // 完成数据传输后,需及时释放内存
    aclrtFreeHost(inputAddr);
    inputAddr = nullptr;
} 
else {
    // 将输入图片读入内存中,该自定义函数ReadPicFile由用户实现
    ReadPicFile(picName, inputPic.picture_address, inputPic.picture_buffer_size);
    }

// 5.3 构造存放输出图片信息的结构体
hi_vpc_pic_info outputPic;
outputPic.picture_width = 960;
outputPic.picture_height  = 540;
outputPic.picture_format = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
outputPic.picture_width_stride = 960;
outputPic.picture_height_stride = 540;
outputPic.picture_buffer_size = outputPic.picture_width_stride * outputPic.picture_height_stride * 3 / 2;
ret = hi_mpi_dvpp_malloc(0, &outputPic.picture_address, outputPic.picture_buffer_size);

// 初始化内存
if (runMode == ACL_HOST) {
    aclRet = aclrtMemset(outputPic.picture_address, outputPic.picture_buffer_size, 0, outputPic.picture_buffer_size);
} else {
     memset(outputPic.picture_address, 0, outputPic.picture_buffer_size);
}

// 5.4 调用缩放接口
uint32_t taskID = 0;
ret = hi_mpi_vpc_resize(chnId, &inputPic, &outputPic, 0, 0, 0, &taskID, -1);

// 5.5 等待任务处理结束,任务处理结束后,输出图片数据在outputPic.picture_address指向的内存中
uint32_t taskIDResult = taskID;
ret = hi_mpi_vpc_get_process_result(chnId, taskIDResult, -1);

// 5.6 如果运行模式为ACL_HOST,且Host上需要展示VPC输出的图片数据,则需要申请Host内存,通过aclrtMemcpy接口将Device的输出图片数据传输到Host;如果Host上不需要展示VPC输出的图片数据,则VPC的输出图片数据可以直接作为模型推理的输入
if (g_runMode == ACL_HOST) {
    hi_vpc_pic_info outputPicHost = outputPic;
    aclRet = aclrtMallocHost(&outputPicHost.picture_address, outputPic.picture_buffer_size);
    aclRet = aclrtMemcpy(outputPicHost.picture_address, outputPic.picture_buffer_size, outputPic.picture_address,outputPic.picture_buffer_size, ACL_MEMCPY_DEVICE_TO_HOST);
    // ......
    // Host侧的数据使用完成后,释放Host内存
    aclrtFreeHost(outputPicHost.picture_address);
    outputPicHost.picture_address = nullptr;
} else {
    // 可以直接使用VPC的输出图片数据,在outputPic.picture_address指向的内存中
    // TODO:推理相关的代码逻辑
}

// 5.7 释放输入、输出内存
ret = hi_mpi_dvpp_free(inputPic.picture_address);
ret = hi_mpi_dvpp_free(outputPic.picture_address);

// 6.销毁通道
ret = hi_mpi_vpc_destroy_chn(chnId);

// 7. 媒体数据处理系统去初始化
ret = hi_mpi_sys_exit();

// 8. 释放运行管理资源(依次释放Context、Device)
aclRet = aclrtDestroyContext(g_context);
aclRet = aclrtResetDevice(0);

// 9.AscendCL去初始化
aclRet = aclFinalize();

// ....