vpc_util.cpp 13.2 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"

#define INFO_LOG(fmt, args...) fprintf(stdout, "[INFO]  " fmt "\n", ##args)
#define WARN_LOG(fmt, args...) fprintf(stdout, "[WARN]  " fmt "\n", ##args)
#define ERROR_LOG(fmt, args...) fprintf(stderr, "[ERROR]  " fmt "\n", ##args)



void VPCUtil::vpc_crop_release()
{
    aclError ret;
    // ret = aclrtSetDevice(deviceId_);
    // aclrtSetCurrentContext(context_);

    ret = acldvppDestroyChannel(dvppChannelDesc_);
    ret = acldvppDestroyChannelDesc(dvppChannelDesc_);

    if (stream_ != nullptr) {
        ret = aclrtDestroyStream(stream_);
        if (ret != ACL_SUCCESS) {
            ERROR_LOG("destroy stream failed");
        }
        stream_ = nullptr;
    }
    INFO_LOG("end to destroy stream");

    if (context_ != nullptr) {
        ret = aclrtDestroyContext(context_);
        if (ret != ACL_SUCCESS) {
            ERROR_LOG("destroy context failed");
        }
        context_ = nullptr;
    }
    INFO_LOG("end to destroy context");

    ret = aclrtResetDevice(deviceId_);
    if (ret != ACL_SUCCESS) {
        ERROR_LOG("reset device failed");
    }
    INFO_LOG("end to reset device is %d", deviceId_);
}


int VPCUtil::vpc_crop(acldvppPicDesc *input_pic_desc, video_object_info obj)
{
    const int orimodelInputWidth = obj.right - obj.left; // cur model shape is 224 * 224
    const int orimodelInputHeight = obj.bottom - obj.top;
    const int modelInputLeft = obj.left; // cur model shape is 224 * 224
    const int modelInputTop = obj.top;

    // GetPicDevBuffer4JpegD
    int modelInputWidth = (orimodelInputWidth + 15) / 16 * 16;
    int modelInputHeight = (orimodelInputHeight + 1) / 2 * 2;
    
    uint32_t oddNum = 1;
    uint32_t cropSizeWidth = modelInputWidth;
    uint32_t cropSizeHeight = modelInputHeight;
    uint32_t cropLeftOffset = modelInputLeft;  // must even
    uint32_t cropRightOffset = cropLeftOffset + cropSizeWidth - oddNum;  // must odd
    uint32_t cropTopOffset = modelInputTop;  // must even
    uint32_t cropBottomOffset = cropTopOffset + cropSizeHeight - oddNum;  // must odd
    acldvppRoiConfig  *cropArea_ = acldvppCreateRoiConfig(cropLeftOffset, cropRightOffset, cropTopOffset, cropBottomOffset);

    /* processdecode */
    uint32_t vpcOutBufferSize_ = modelInputWidth * modelInputHeight * 3 / 2;
    void *vpcOutBufferDev_ = nullptr;
    acldvppMalloc(&vpcOutBufferDev_, vpcOutBufferSize_);
    acldvppPicDesc *vpcOutputDesc_ = acldvppCreatePicDesc();
    acldvppSetPicDescData(vpcOutputDesc_, vpcOutBufferDev_);
    acldvppSetPicDescFormat(vpcOutputDesc_, PIXEL_FORMAT_YUV_SEMIPLANAR_420);
    acldvppSetPicDescWidth(vpcOutputDesc_, modelInputWidth);
    acldvppSetPicDescHeight(vpcOutputDesc_, modelInputHeight);
    acldvppSetPicDescWidthStride(vpcOutputDesc_, modelInputWidth);
    acldvppSetPicDescHeightStride(vpcOutputDesc_, modelInputHeight);
    acldvppSetPicDescSize(vpcOutputDesc_, vpcOutBufferSize_);

    int ret = acldvppVpcCropAsync(dvppChannelDesc_, input_pic_desc, vpcOutputDesc_, cropArea_, stream_);

    ret = aclrtSynchronizeStream(stream_);

    /* DestroycropResource */
    (void)acldvppDestroyRoiConfig(cropArea_);
    cropArea_ = nullptr;
    (void)acldvppDestroyPicDesc(vpcOutputDesc_);
    vpcOutputDesc_ = nullptr;

    if (vpcOutBufferDev_ != nullptr) {
        (void)acldvppFree(vpcOutBufferDev_);
	    vpcOutBufferDev_ = nullptr;
    }

    return 0;
}

int VPCUtil::vpc_crop_init(int32_t devId){
    deviceId_ = devId;

    aclError ret;
    /* 2.Run the management resource application, including Device, Context, Stream */
    aclrtSetDevice(deviceId_);
    aclrtCreateContext(&context_, deviceId_);
    aclrtCreateStream(&stream_);

    // channel  准备
    dvppChannelDesc_ = acldvppCreateChannelDesc();
    ret = acldvppCreateChannel(dvppChannelDesc_);

}

static void check_coordinate(uint32_t& cropLeftOffset, uint32_t& cropRightOffset, uint32_t& cropTopOffset, uint32_t& cropBottomOffset, uint32_t width, uint32_t height){
    if (cropLeftOffset < 0){
        cropLeftOffset = 0;
    }
    if (cropTopOffset < 0){
        cropTopOffset = 0;
    }
    if(cropRightOffset > width){
        cropRightOffset = width;
    }
    if(cropBottomOffset > height){
        cropBottomOffset = height;
    }
    
}

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

    vector<vpc_img_info> vec_img_info;

    /* 1.ACL initialization  */
    // aclInit(nullptr);
    aclError ret;
    aclrtSetDevice(deviceId_);
    ret = aclrtSetCurrentContext(context_);

    // 输入
	acldvppBatchPicDesc *vpcInputBatchDesc_ = acldvppCreateBatchPicDesc(1);
	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());

    const uint32_t outputBatchSize_ = objs.size();
    // 输出
    acldvppBatchPicDesc *outputBatchPicDesc_ = acldvppCreateBatchPicDesc(outputBatchSize_);
    if (outputBatchPicDesc_ == nullptr) {
        ERROR_LOG("acldvppCreatePicDesc outBatchPicDesc failed");
        return vec_img_info;
    }
    vector<void *> vecOutPtr_;
    acldvppPicDesc *vpcOutputDesc = nullptr;
    // acldvppRoiConfig cropAreas[outputBatchSize_];
    // std::unique_ptr<acldvppRoiConfig *[]>
    //     cropAreas(new(std::nothrow) acldvppRoiConfig *[outputBatchSize_ * sizeof(acldvppRoiConfig *)]);
    acldvppRoiConfig *cropAreas[outputBatchSize_];
    for (uint32_t i = 0; i < outputBatchSize_; i++) {
        video_object_info obj = objs[i];

        int orimodelInputWidth = obj.right - obj.left; 
        int orimodelInputHeight = obj.bottom - obj.top;
        // GetPicDevBuffer4JpegD
        int modelInputWidth = (orimodelInputWidth + 15) / 16 * 16;
        int modelInputHeight = (orimodelInputHeight + 1) / 2 * 2;

        uint32_t oddNum = 1;
        uint32_t cropSizeWidth = modelInputWidth;
        uint32_t cropSizeHeight = modelInputHeight;
        uint32_t cropLeftOffset = obj.left;  // must even
        uint32_t cropRightOffset = obj.right;//cropLeftOffset + cropSizeWidth - oddNum;  // must odd
        uint32_t cropTopOffset = obj.top;  // must even
        uint32_t cropBottomOffset = obj.bottom;//cropTopOffset + cropSizeHeight - oddNum;  // must odd

        check_coordinate(cropLeftOffset, cropRightOffset, cropTopOffset, cropBottomOffset, devMem->getWidth(), devMem->getHeight());
        
        cropAreas[i] = acldvppCreateRoiConfig(cropLeftOffset, cropRightOffset, cropTopOffset, cropBottomOffset);

        uint32_t vpcOutBufferSize_ = modelInputWidth * modelInputHeight * 3 / 2;
        void *vpcBatchOutputBufferDev = nullptr;
        auto ret = acldvppMalloc(&vpcBatchOutputBufferDev, vpcOutBufferSize_);
        if (ret != ACL_SUCCESS) {
            ERROR_LOG("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]);
                }
            }
            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, modelInputWidth);
        (void)acldvppSetPicDescHeight(vpcOutputDesc, modelInputHeight);
        (void)acldvppSetPicDescWidthStride(vpcOutputDesc, modelInputWidth);
        (void)acldvppSetPicDescHeightStride(vpcOutputDesc, modelInputHeight);
        (void)acldvppSetPicDescSize(vpcOutputDesc, vpcOutBufferSize_);
    }

    uint32_t roiNums[] = { outputBatchSize_ };
    ret = acldvppVpcBatchCropAsync(dvppChannelDesc_, vpcInputBatchDesc_, roiNums, 1, outputBatchPicDesc_, cropAreas, stream_);
    ret = aclrtSynchronizeStream(stream_);

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

    aclrtSetCurrentContext(context_);

    if (vpcInputBatchDesc_ != nullptr) {
        (void)acldvppDestroyBatchPicDesc(vpcInputBatchDesc_);
        vpcInputBatchDesc_ = nullptr;
    }

    // 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) {
        ERROR_LOG("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_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();
}