vpc_util.cpp 15.3 KB

#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include <dirent.h>
#include <fstream>
#include <cstring>
#include <vector>
#include <sys/types.h>
#include <sys/stat.h>
#include <map>
#include <cstdint>
#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"

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_);
}

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

    if(cropRightOffset <= cropLeftOffset || cropBottomOffset <= cropTopOffset){
        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
    {
        aclError 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_);

}

vector<vpc_img_info> VPCUtil::crop_batch(DeviceMemory *devMem, vector<video_object_info> objs){

    vector<vpc_img_info> 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<void *> 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

        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<int32_t>(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<int32_t>(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<vpc_img_info>& imgList){
    for(int i=0; i < imgList.size(); i++){
        vpc_img_release(imgList[i]);
    }
    imgList.clear();
}