DVPP使用
图像/视频编解码
框架提供了图像处理单元以及视频编解码能力的调用接口,用户可以根据实际情况,将图像的解码/视频的解码放到Device上,以减少从Host到Device传输的数据量,同时降低数据传输时间开销和带宽压力。
在Host侧,通过调用Matrix框架提供HIAI_DMalloc申请Device侧的内存,作为图像/视频编解码的输入使用,数据存放的内存位置建议起始地址128对齐。在Device侧,DVPP完成图像/视频预处理后,调用Matrix框架提供HIAI_DVPP_DMalloc申请内存,作为图像预处理后的输出使用。
图像Crop/Resize
在Ascend 310上编程,图像crop/resize推荐使用DVPP来实现。
crop/resize运行示意图如图9-4所示,它可以完成在图像中对ROI区域进行截图并使用这个截图进行重采样的过程。截图称为crop,重采样称之为resize。当resize系数为1时,相当于只做crop。当crop为原图时,相当于只做resize。
crop/resize对输入的限制如下:
- 输入数据地址(os虚拟地址):16字节对齐。
- 输入图像宽度内存限制:16字节对齐。
- 输入图像高度内存限制:2字节对齐。
基于上述限制,高性能的编程方式要实现“0拷贝”则需要满足从Device(接收端)给用户的内存地址开始就满足限制。一般的做法根据输入不同分为以下两种做法。
- 方法一:在Host进行解码或者在其他硬件进行解码的应用,在Host发送端将数据就做好裁剪或者padding,满足16*2对齐,这样框架在数据接收端会自动的申请满足上述限制的数据内存。
示例的输入数据是YUV图片,所以计算图片SIZE都是通过(ImageWidth * ImageHeight) * 3/2的方式,其他格式的数据,根据图片格式自行调整。
static const uint32_t ALIGN_W = 16; static const uint32_t ALIGN_H = 2; uint32_t imageWidth = 500; uint32_t imageHeight = 333; uint32_t imageSize = imageWidth * imageHeight *3/2; uint32_t align_width = image_width, align_height = image_height; // 进行宽高对齐 alignWidth = (alignWidth % ALIGN_W) ? alignWidth : (imageWidth + ALIGN_W)/ALIGN_W* ALIGN_W; alignHeight = (alignHeight % ALIGN_H) ? alignHeight : (imageHeight + ALIGN_H)/ALIGN_H * ALIGN_H; uint32_t alignSize = alignWidth * alignHeight *3/2; // 读取文件数据, 拷贝对齐内存 FILE *fpIn = fopen(filePath.data(), "rb"); Uint8_t* imageBuffer = (uint8_t*) malloc(imageSize); HIAI_StatusT getRet = hiai::HIAIMemory::HIAI_DMalloc(fileLen, (void*&)alignBuffer, 10000); size_t size = fread(imageBuffer, 1, imageSize, fpIn); // 进行拷贝 Uint32_t tempLen = imageWidth * imageHeight; if (alignWidth == imageWidth) { if(alignHeight > imageHeight) { memcpy_s(alignBuffer, tempLen, imageBuffer, tempLen); memcpy_s(alignBuffer + alignHeight * alignWidth, tempLen/2, imageBuffer + tempLen, tempLen/2); } } else { for(int32_t n=0;n<imageHeight;n++) { memcpy_s(alignBuffer+n*alingWidth,imageWidth, imageBuffer+n*imageWidth,imageWidth); } for(int32_t n=0;n<imageHeight/2;n++) { memcpy_s(alignBuffer+n*alignWidth+alignHeight* alignWidth, imageWidth, imageBuffer+n* imageWidth + imageHeight*imageWidth,imageWidth);//UV } }
- 方法二:在Device进行图片解码、视频解码以后输出为16*2对齐,可直接作为DVPP VPC(Crop&&Resize)输入。