#include #include #include #include #include #include #include #include #include #include #include #include "acl/acl.h" #include "acl/ops/acl_dvpp.h" #include "vpc_util.h" #include "JpegUtil.h" #include "../decoder/interface/DeviceMemory.hpp" #include "../common/logger.hpp" static uint32_t AlignSize(uint32_t origSize, uint32_t alignment){ if (alignment == 0) { return 0; } uint32_t alignmentH = alignment - 1; return (origSize + alignmentH) / alignment * alignment; } void VPCUtil::release() { aclError ret; // ret = aclrtSetDevice(deviceId_); // aclrtSetCurrentContext(context_); ret = acldvppDestroyChannel(dvppChannelDesc_); ret = acldvppDestroyChannelDesc(dvppChannelDesc_); if (context_ != nullptr) { ret = aclrtDestroyContext(context_); if (ret != ACL_SUCCESS) { LOG_ERROR("destroy context failed"); } context_ = nullptr; } LOG_INFO("end to destroy context"); ret = aclrtResetDevice(deviceId_); if (ret != ACL_SUCCESS) { LOG_ERROR("reset device failed"); } LOG_INFO("end to reset device is %d", deviceId_); } static void adjustCoordinate(uint32_t& left, uint32_t& right, uint32_t& top, uint32_t& bottom, const uint32_t& width, const uint32_t& height) { uint32_t cropWidth = right - left; uint32_t cropHeight = bottom - top; if(cropWidth < 16) { cropWidth += 16; //小于16的似乎抠不了图 right += 16; } if (left < 0) { left = 0; right = cropWidth; } if (right >= width){ right = width -1; left = right - cropWidth; } if (top < 0) { top = 0; bottom = cropHeight; } if (bottom >= height){ bottom = height -1; top = bottom - cropHeight; } } vpc_img_info VPCUtil::crop(DeviceMemory *devMem, video_object_info obj) { vpc_img_info img_info; // uint32_t cropSizeWidth = (obj.right - obj.left) / 16 * 16; // uint32_t cropSizeHeight = (obj.bottom - obj.top) / 2 * 2; uint32_t cropSizeWidth = (obj.right - obj.left + 15) / 16 * 16; //debug by zsh uint32_t cropSizeHeight = (obj.bottom - obj.top + 1) / 2 * 2; uint32_t oddNum = 1; uint32_t cropLeftOffset = (obj.left + 1) / 2 * 2; // must even uint32_t cropRightOffset = cropLeftOffset + cropSizeWidth - oddNum; // must odd uint32_t cropTopOffset = (obj.top + 1) / 2 * 2; // must even uint32_t cropBottomOffset = cropTopOffset + cropSizeHeight - oddNum; // must odd adjustCoordinate(cropLeftOffset, cropRightOffset, cropTopOffset, cropBottomOffset, devMem->getWidth(), devMem->getHeight()); cropSizeWidth = cropRightOffset - cropLeftOffset + oddNum; // 宽高要比实际的高才行,否则会抠图失败 cropSizeHeight = cropBottomOffset - cropTopOffset + oddNum; // LOG_DEBUG("{} ,{} ,{} ,{} ", cropLeftOffset, cropRightOffset, cropTopOffset, cropBottomOffset); if(cropRightOffset <= cropLeftOffset || cropBottomOffset <= cropTopOffset){ LOG_ERROR("{} <= {} || {} <= {} ", cropRightOffset, cropLeftOffset, cropBottomOffset, cropTopOffset); return img_info; } aclError ret; aclrtSetDevice(deviceId_); ret = aclrtSetCurrentContext(context_); if (ret != ACL_SUCCESS) { LOG_ERROR("aclrtSetCurrentContext failed"); return img_info; } // LOG_INFO("crop src {} ({}, {}, {}, {})", obj.object_id, obj.left, obj.right, obj.top, obj.bottom); // LOG_INFO("crop {} ({}, {}, {}, {})", obj.object_id, cropLeftOffset, cropRightOffset, cropTopOffset, cropBottomOffset); acldvppRoiConfig *cropArea_ = acldvppCreateRoiConfig(cropLeftOffset, cropRightOffset, cropTopOffset, cropBottomOffset); acldvppPicDesc *vpcInputDesc_ = acldvppCreatePicDesc(); acldvppSetPicDescData(vpcInputDesc_, devMem->getMem()); acldvppSetPicDescFormat(vpcInputDesc_, PIXEL_FORMAT_YUV_SEMIPLANAR_420); acldvppSetPicDescWidth(vpcInputDesc_, devMem->getWidth()); acldvppSetPicDescHeight(vpcInputDesc_, devMem->getHeight()); acldvppSetPicDescWidthStride(vpcInputDesc_, devMem->getWidthStride()); acldvppSetPicDescHeightStride(vpcInputDesc_, devMem->getHeightStride()); acldvppSetPicDescSize(vpcInputDesc_, devMem->getSize()); /* processdecode */ uint32_t vpcOutBufferSize_ = cropSizeWidth * cropSizeHeight * 3 / 2; void *vpcOutBufferDev_ = nullptr; acldvppMalloc(&vpcOutBufferDev_, vpcOutBufferSize_); acldvppPicDesc *vpcOutputDesc_ = acldvppCreatePicDesc(); acldvppSetPicDescData(vpcOutputDesc_, vpcOutBufferDev_); acldvppSetPicDescFormat(vpcOutputDesc_, PIXEL_FORMAT_YUV_SEMIPLANAR_420); acldvppSetPicDescWidth(vpcOutputDesc_, cropSizeWidth); acldvppSetPicDescHeight(vpcOutputDesc_, cropSizeHeight); acldvppSetPicDescWidthStride(vpcOutputDesc_, cropSizeWidth); acldvppSetPicDescHeightStride(vpcOutputDesc_, cropSizeHeight); acldvppSetPicDescSize(vpcOutputDesc_, vpcOutBufferSize_); aclrtStream stream_; aclrtCreateStream(&stream_); bool bRet = false; do { ret = acldvppVpcCropAsync(dvppChannelDesc_, vpcInputDesc_, vpcOutputDesc_, cropArea_, stream_); if (ret != ACL_SUCCESS) { LOG_ERROR("acldvppVpcCropAsync failed, task_id : {}", devMem->getId()); break; } ret = aclrtSynchronizeStream(stream_); if (ret != ACL_SUCCESS) { LOG_ERROR("aclrtSynchronizeStream failed, task_id : {}", devMem->getId()); break; } img_info.pic_desc = vpcOutputDesc_; img_info.object_id = obj.object_id; img_info.task_id = obj.task_id; //该物体属于的任务ID号 img_info.task_frame_count = obj.task_frame_count; //该物体当前出现的帧号 img_info.index = obj.index; //该物体所属类别的编号 img_info.confidence = obj.confidence; //该物体的置信度 bRet = true; } while (0); if (stream_ != nullptr) { aclrtDestroyStream(stream_); } acldvppDestroyPicDesc(vpcInputDesc_); /* DestroycropResource */ (void)acldvppDestroyRoiConfig(cropArea_); cropArea_ = nullptr; if (!bRet) { (void)acldvppDestroyPicDesc(vpcOutputDesc_); vpcOutputDesc_ = nullptr; if (vpcOutBufferDev_ != nullptr) { (void)acldvppFree(vpcOutBufferDev_); vpcOutBufferDev_ = nullptr; } } return img_info; } int VPCUtil::init(int32_t devId){ deviceId_ = devId; aclError ret; aclrtSetDevice(deviceId_); aclrtCreateContext(&context_, deviceId_); // channel 准备 dvppChannelDesc_ = acldvppCreateChannelDesc(); ret = acldvppCreateChannel(dvppChannelDesc_); if(ret != ACL_ERROR_NONE){ LOG_ERROR("acldvppCreateChannel failed!"); exit(-2); } return 0; } vector VPCUtil::crop_batch(DeviceMemory *devMem, vector objs){ vector vec_img_info; const uint32_t outputBatchSize_ = objs.size(); if(outputBatchSize_ <= 0){ return vec_img_info; } aclError ret; aclrtSetDevice(deviceId_); ret = aclrtSetCurrentContext(context_); // 输入 acldvppBatchPicDesc *vpcInputBatchDesc_ = acldvppCreateBatchPicDesc(1); if (vpcInputBatchDesc_ == nullptr) { LOG_ERROR("acldvppCreatePicDesc outBatchPicDesc failed"); return vec_img_info; } acldvppPicDesc *vpcInputDesc_ = acldvppGetPicDesc(vpcInputBatchDesc_, 0); acldvppSetPicDescData(vpcInputDesc_, devMem->getMem()); acldvppSetPicDescFormat(vpcInputDesc_, PIXEL_FORMAT_YUV_SEMIPLANAR_420); acldvppSetPicDescWidth(vpcInputDesc_, devMem->getWidth()); acldvppSetPicDescHeight(vpcInputDesc_, devMem->getHeight()); acldvppSetPicDescWidthStride(vpcInputDesc_, devMem->getWidthStride()); acldvppSetPicDescHeightStride(vpcInputDesc_, devMem->getHeightStride()); acldvppSetPicDescSize(vpcInputDesc_, devMem->getSize()); // 输出 acldvppBatchPicDesc *outputBatchPicDesc_ = acldvppCreateBatchPicDesc(outputBatchSize_); if (outputBatchPicDesc_ == nullptr) { LOG_ERROR("acldvppCreatePicDesc outBatchPicDesc failed"); (void)acldvppDestroyBatchPicDesc(vpcInputBatchDesc_); return vec_img_info; } vector vecOutPtr_; acldvppPicDesc *vpcOutputDesc = nullptr; acldvppRoiConfig *cropAreas[outputBatchSize_]; for (uint32_t i = 0; i < outputBatchSize_; i++) { video_object_info obj = objs[i]; // uint32_t cropSizeWidth = (obj.right - obj.left) / 16 * 16; // uint32_t cropSizeHeight = (obj.bottom - obj.top) / 2 * 2; uint32_t cropSizeWidth = (obj.right - obj.left + 15) / 16 * 16; //debug by zsh uint32_t cropSizeHeight = (obj.bottom - obj.top + 1) / 2 * 2; uint32_t oddNum = 1; uint32_t cropLeftOffset = (obj.left + 1) / 2 * 2; // must even uint32_t cropRightOffset = cropLeftOffset + cropSizeWidth - oddNum; // must odd uint32_t cropTopOffset = (obj.top + 1) / 2 * 2; // must even uint32_t cropBottomOffset = cropTopOffset + cropSizeHeight - oddNum; // must odd adjustCoordinate(cropLeftOffset, cropRightOffset, cropTopOffset, cropBottomOffset, devMem->getWidth(), devMem->getHeight()); cropSizeWidth = cropRightOffset - cropLeftOffset + oddNum; cropSizeHeight = cropBottomOffset - cropTopOffset + oddNum; // LOG_DEBUG("{} ,{} ,{} ,{} ", cropLeftOffset, cropRightOffset, cropTopOffset, cropBottomOffset); if(cropRightOffset <= cropLeftOffset || cropBottomOffset <= cropTopOffset){ LOG_ERROR("{} <= {} || {} <= {} ", cropRightOffset, cropLeftOffset, cropBottomOffset, cropTopOffset); // 释放之前成功的部分 再退出 for(int i = 0; i < vecOutPtr_.size(); i++){ if (vecOutPtr_[i] != nullptr){ acldvppFree(vecOutPtr_[i]); } if (cropAreas[i] != nullptr) { (void)acldvppDestroyRoiConfig(cropAreas[i]); cropAreas[i] = nullptr; } } return vec_img_info; } cropAreas[i] = acldvppCreateRoiConfig(cropLeftOffset, cropRightOffset, cropTopOffset, cropBottomOffset); uint32_t vpcOutBufferSize_ = cropSizeWidth * cropSizeHeight * 3 / 2; void *vpcBatchOutputBufferDev = nullptr; auto ret = acldvppMalloc(&vpcBatchOutputBufferDev, vpcOutBufferSize_); if (ret != ACL_SUCCESS) { LOG_ERROR("acldvppMalloc failed, size = %u, errorCode = %d.", vpcOutBufferSize_, static_cast(ret)); // 释放之前成功的部分 再退出 for(int i = 0; i < vecOutPtr_.size(); i++){ if (vecOutPtr_[i] != nullptr){ acldvppFree(vecOutPtr_[i]); } if (cropAreas[i] != nullptr) { (void)acldvppDestroyRoiConfig(cropAreas[i]); cropAreas[i] = nullptr; } } return vec_img_info; } vecOutPtr_.push_back(vpcBatchOutputBufferDev); vpcOutputDesc = acldvppGetPicDesc(outputBatchPicDesc_, i); (void)acldvppSetPicDescData(vpcOutputDesc, vpcBatchOutputBufferDev); (void)acldvppSetPicDescFormat(vpcOutputDesc, PIXEL_FORMAT_YUV_SEMIPLANAR_420); (void)acldvppSetPicDescWidth(vpcOutputDesc, cropSizeWidth); (void)acldvppSetPicDescHeight(vpcOutputDesc, cropSizeHeight); (void)acldvppSetPicDescWidthStride(vpcOutputDesc, cropSizeWidth); (void)acldvppSetPicDescHeightStride(vpcOutputDesc, cropSizeHeight); (void)acldvppSetPicDescSize(vpcOutputDesc, vpcOutBufferSize_); } aclrtStream stream_; aclrtCreateStream(&stream_); bool bRet = false; do { uint32_t roiNums[] = { outputBatchSize_ }; ret = acldvppVpcBatchCropAsync(dvppChannelDesc_, vpcInputBatchDesc_, roiNums, 1, outputBatchPicDesc_, cropAreas, stream_); if (ret != ACL_SUCCESS) { LOG_ERROR("acldvppVpcBatchCropAsync failed, task_id : {}", devMem->getId()); break; } ret = aclrtSynchronizeStream(stream_); if (ret != ACL_SUCCESS) { LOG_ERROR("aclrtSynchronizeStream failed, task_id : {}", devMem->getId()); break; } for (uint32_t i = 0; i < outputBatchSize_; i++) { video_object_info obj = objs[i]; vpcOutputDesc = acldvppGetPicDesc(outputBatchPicDesc_, i); void *outputDataDev = acldvppGetPicDescData(vpcOutputDesc); uint32_t outputSize = acldvppGetPicDescSize(vpcOutputDesc); uint32_t width = acldvppGetPicDescWidth(vpcOutputDesc); uint32_t width_stride = acldvppGetPicDescWidthStride(vpcOutputDesc); uint32_t height = acldvppGetPicDescHeight(vpcOutputDesc); uint32_t height_stride = acldvppGetPicDescHeightStride(vpcOutputDesc); acldvppPixelFormat fmt = acldvppGetPicDescFormat(vpcOutputDesc); acldvppPicDesc *vpcInputDesc_= acldvppCreatePicDesc(); acldvppSetPicDescData(vpcInputDesc_, vecOutPtr_[i]); acldvppSetPicDescFormat(vpcInputDesc_, fmt); acldvppSetPicDescWidth(vpcInputDesc_, width); acldvppSetPicDescHeight(vpcInputDesc_, height); acldvppSetPicDescWidthStride(vpcInputDesc_, width_stride); acldvppSetPicDescHeightStride(vpcInputDesc_, height_stride); acldvppSetPicDescSize(vpcInputDesc_, outputSize); vpc_img_info img_info ; img_info.pic_desc = vpcInputDesc_; img_info.object_id = obj.object_id; img_info.task_id = obj.task_id; //该物体属于的任务ID号 img_info.task_frame_count = obj.task_frame_count; //该物体当前出现的帧号 img_info.index = obj.index; //该物体所属类别的编号 img_info.confidence = obj.confidence; //该物体的置信度 vec_img_info.push_back(img_info); // vpcOutputDesc = acldvppGetPicDesc(outputBatchPicDesc_, i); // string file_name = "output"; // file_name = file_name + to_string(i) + ".jpg"; // vpc_jpeg_encode(vpcOutputDesc, file_name); } bRet = true; } while (0); if (stream_ != nullptr) { aclrtDestroyStream(stream_); } aclrtSetCurrentContext(context_); if (vpcInputBatchDesc_ != nullptr) { (void)acldvppDestroyBatchPicDesc(vpcInputBatchDesc_); vpcInputBatchDesc_ = nullptr; } if (!bRet){ for(int i = 0; i < vecOutPtr_.size(); i++){ if (vecOutPtr_[i] != nullptr){ acldvppFree(vecOutPtr_[i]); } } } if (outputBatchPicDesc_ != nullptr) { (void)acldvppDestroyBatchPicDesc(outputBatchPicDesc_); outputBatchPicDesc_ = nullptr; } // for (size_t i = 0; i < vec_img_info.size(); i++) // { // if(vec_img_info[i].pic_desc != nullptr){ // void *outputDataDev = acldvppGetPicDescData(vec_img_info[i].pic_desc); // acldvppFree(outputDataDev); // acldvppDestroyPicDesc(vec_img_info[i].pic_desc); // } // } for (uint32_t i = 0; i < outputBatchSize_; i++) { if (cropAreas[i] != nullptr) { (void)acldvppDestroyRoiConfig(cropAreas[i]); cropAreas[i] = nullptr; } } return vec_img_info; } vpc_img_info VPCUtil::vpc_devMem2vpcImg(DeviceMemory *devMem){ vpc_img_info img_info ; int nBufferSize = devMem->getSize(); void *devBuffer = nullptr; auto ret = acldvppMalloc(&devBuffer, nBufferSize); if (ret != ACL_SUCCESS) { LOG_ERROR("acldvppMalloc failed, size = %u, errorCode = %d.", nBufferSize, static_cast(ret)); // 这里应释放之前成功的部分 再退出 return img_info; } aclrtMemcpy(devBuffer, nBufferSize, devMem->getMem(), nBufferSize, ACL_MEMCPY_DEVICE_TO_DEVICE); acldvppPicDesc *vpcInputDesc_= acldvppCreatePicDesc(); acldvppSetPicDescData(vpcInputDesc_, devBuffer); acldvppSetPicDescFormat(vpcInputDesc_, PIXEL_FORMAT_YUV_SEMIPLANAR_420); acldvppSetPicDescWidth(vpcInputDesc_, devMem->getWidth()); acldvppSetPicDescHeight(vpcInputDesc_, devMem->getHeight()); acldvppSetPicDescWidthStride(vpcInputDesc_, devMem->getWidthStride()); acldvppSetPicDescHeightStride(vpcInputDesc_, devMem->getHeightStride()); acldvppSetPicDescSize(vpcInputDesc_, devMem->getSize()); img_info.pic_desc = vpcInputDesc_; img_info.object_id = -1; img_info.task_id = devMem->getId(); //该物体属于的任务ID号 img_info.index = -1; //该物体所属类别的编号 img_info.confidence = 0.0; //该物体的置信度 return img_info; } void VPCUtil::vpc_pic_desc_release(acldvppPicDesc* pic_desc){ void *outputDataDev = acldvppGetPicDescData(pic_desc); acldvppFree(outputDataDev); acldvppDestroyPicDesc(pic_desc); } void VPCUtil::vpc_img_release(vpc_img_info img_info){ if(img_info.pic_desc != nullptr){ void *outputDataDev = acldvppGetPicDescData(img_info.pic_desc); acldvppFree(outputDataDev); acldvppDestroyPicDesc(img_info.pic_desc); } } void VPCUtil::vpc_imgList_release(vector& imgList){ for(int i=0; i < imgList.size(); i++){ vpc_img_release(imgList[i]); } imgList.clear(); }