JpegUtil.cpp 3.48 KB
#include <cstdio>
#include <cstdlib>
#include <memory>
#include "JpegUtil.h"
#include "../common/logger.hpp"

using namespace std;


int JpegUtil::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_);

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

void JpegUtil::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) {
            LOG_ERROR("destroy stream failed");
        }
        stream_ = nullptr;
    }

    acldvppDestroyJpegeConfig(jpegeConfig_);

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

    ret = aclrtResetDevice(deviceId_);
    if (ret != ACL_SUCCESS) {
        LOG_ERROR("reset device failed");
    }
}

int32_t JpegUtil::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) {
        LOG_ERROR("open output file err");
        return 1;
    }

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

    fclose(fd);
    return 0;
}

void JpegUtil::jpeg_encode(acldvppPicDesc *encodeInputDesc_, string out_file_name) {

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

    // 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;
    // 数据使用完成后,释放内存
    jpege_save((char*)outputHostBuffer, outBufferSize, out_file_name);
    free(outputHostBuffer);
    outputHostBuffer = nullptr;
}