JpegUtil.cpp 3.98 KB
#include <cstdio>
#include <cstdlib>
#include <memory>
#include "JpegUtil.h"

using namespace std;

namespace DVPP_UTIL {

    int32_t deviceId_;
    aclrtContext context_;
    aclrtStream stream_;
    acldvppChannelDesc *dvppChannelDesc_;

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

    void dvpp_jpeg_release(){
        aclError ret;
        ret = aclrtSetDevice(deviceId_);
        aclrtSetCurrentContext(context_);

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

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

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

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

    int32_t dvpp_jpege_save(char* pcData , uint32_t dataLen, string out_file_name)
    {
        FILE* fd = nullptr;
        fd = fopen(out_file_name.c_str(), "wb");
        if (fd == nullptr) {
            printf("open output file err\n");
            return 1;
        }

        fwrite(pcData, dataLen, 1, fd);
        fflush(fd);

        fclose(fd);
        return 0;
    }

    void dvpp_jpeg_encode(acldvppPicDesc *encodeInputDesc_, string out_file_name){

        aclError aclRet ;
        aclRet = aclrtSetDevice(deviceId_);
        aclrtSetCurrentContext(context_);

        // 7. 创建图片编码配置数据,设置编码质量
        // 编码质量范围[0, 100],其中level 0编码质量与level 100差不多,而在[1, 100]内数值越小输出图片质量越差。
        acldvppJpegeConfig *jpegeConfig_ = acldvppCreateJpegeConfig();
        acldvppSetJpegeConfigLevel(jpegeConfig_, 100);

        // 8. 申请输出内存,申请Device内存encodeOutBufferDev_,存放编码后的输出数据
        uint32_t outBufferSize= 0;
        int ret = acldvppJpegPredictEncSize(encodeInputDesc_, jpegeConfig_, &outBufferSize);
        void *encodeOutBufferDev_ = nullptr;
        ret = acldvppMalloc(&encodeOutBufferDev_, outBufferSize);

        // 9. 执行异步编码,再调用aclrtSynchronizeStream接口阻塞程序运行,直到指定Stream中的所有任务都完成
        aclRet = acldvppJpegEncodeAsync(dvppChannelDesc_, encodeInputDesc_, encodeOutBufferDev_, &outBufferSize, jpegeConfig_, stream_);
        aclRet = aclrtSynchronizeStream(stream_);

        // 该模式下,由于处理结果在Device侧,因此需要调用内存复制接口传输结果数据后,再释放Device侧内存
        // 申请Host内存outputHostBuffer 
        void* outputHostBuffer = malloc(outBufferSize);
        // 通过aclrtMemcpy接口将Device的处理结果数据传输到Host
        aclRet = aclrtMemcpy(outputHostBuffer, outBufferSize, encodeOutBufferDev_, outBufferSize, ACL_MEMCPY_DEVICE_TO_HOST);
        // 释放掉输入输出的device内存
        (void)acldvppFree(encodeOutBufferDev_);
        encodeOutBufferDev_ = nullptr;
        // 数据使用完成后,释放内存
        dvpp_jpege_save((char*)outputHostBuffer, outBufferSize, out_file_name);
        free(outputHostBuffer);
        outputHostBuffer = nullptr;
    }

}