JpegUtil.cpp 4.36 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 error");
        return 1;
    }

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

    fclose(fd);
    return 0;
}

bool 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);
    if (ret != ACL_SUCCESS) {
        LOG_ERROR("acldvppJpegPredictEncSize failed!");
        return false;
    }
    void *encodeOutBufferDev_ = nullptr;
    ret = acldvppMalloc(&encodeOutBufferDev_, outBufferSize);
    if (ret != ACL_SUCCESS) {
        LOG_ERROR("acldvppMalloc failed!");
        return false;
    }

    bool bRet = false;
    do {
        // 9. 执行异步编码,再调用aclrtSynchronizeStream接口阻塞程序运行,直到指定Stream中的所有任务都完成
        aclRet = acldvppJpegEncodeAsync(dvppChannelDesc_, encodeInputDesc_, encodeOutBufferDev_, &outBufferSize, jpegeConfig_, stream_);
        if (ret != ACL_SUCCESS) {
            LOG_ERROR("acldvppJpegEncodeAsync failed!");
            break;
        }
        aclRet = aclrtSynchronizeStream(stream_);
        if (ret != ACL_SUCCESS) {
            LOG_ERROR("aclrtSynchronizeStream failed!");
            break;
        }

        // 申请Host内存outputHostBuffer 
        void* outputHostBuffer = malloc(outBufferSize);
        if(outputHostBuffer == nullptr) {
            LOG_ERROR("malloc failed!");
            break;
        }

        // 通过aclrtMemcpy接口将Device的处理结果数据传输到Host
        aclRet = aclrtMemcpy(outputHostBuffer, outBufferSize, encodeOutBufferDev_, outBufferSize, ACL_MEMCPY_DEVICE_TO_HOST);
        if (ret != ACL_SUCCESS) {
            free(outputHostBuffer);
            outputHostBuffer = nullptr;
            LOG_ERROR("aclrtMemcpy failed!");
            break;
        }

        // 数据使用完成后,释放内存
        ret = jpege_save((char*)outputHostBuffer, outBufferSize, out_file_name);
        free(outputHostBuffer);
        outputHostBuffer = nullptr;
        if(ret != 0) {
            LOG_ERROR("jpege_save failed!");
            break;
        }

        bRet = true;
    } while (0);
    
    // 释放掉输入输出的device内存
    (void)acldvppFree(encodeOutBufferDev_);
    encodeOutBufferDev_ = nullptr;
    aclRet = aclrtResetDevice(deviceId_);
    return bRet;
}