#include #include #include #include "JpegUtil.h" #include "../common/logger.hpp" using namespace std; #define ACL_CHECK_AND_ABORT(ret, message) \ if(ret != 0) {LOG_ERROR("{}", message); std::abort();} int JpegUtil::jpeg_init(int32_t devId){ deviceId_ = devId; ACL_CHECK_AND_ABORT(aclrtCreateContext(&context_, deviceId_), "aclrtCreateContext failed!"); // channel 准备 dvppChannelDesc_ = acldvppCreateChannelDesc(); if (dvppChannelDesc_ == nullptr) { LOG_ERROR("acldvppCreateChannelDesc failed!"); std::abort(); } ACL_CHECK_AND_ABORT(acldvppCreateChannel(dvppChannelDesc_), "acldvppCreateChannel failed!"); // 创建图片编码配置数据,设置编码质量 // 编码质量范围[0, 100],其中level 0编码质量与level 100差不多,而在[1, 100]内数值越小输出图片质量越差。 jpegeConfig_ = acldvppCreateJpegeConfig(); if (jpegeConfig_ == nullptr) { LOG_ERROR("acldvppCreateJpegeConfig failed!"); std::abort(); } ACL_CHECK_AND_ABORT(acldvppSetJpegeConfigLevel(jpegeConfig_, 100), "acldvppSetJpegeConfigLevel failed!"); } void JpegUtil::jpeg_release(){ ACL_CHECK_AND_ABORT(aclrtSetCurrentContext(context_), "aclrtSetCurrentContext failed!"); ACL_CHECK_AND_ABORT(acldvppDestroyChannel(dvppChannelDesc_), "acldvppDestroyChannel failed!"); ACL_CHECK_AND_ABORT(acldvppDestroyChannelDesc(dvppChannelDesc_), "acldvppDestroyChannelDesc failed!"); dvppChannelDesc_ = nullptr; acldvppDestroyJpegeConfig(jpegeConfig_); if (context_ != nullptr) { ACL_CHECK_AND_ABORT(aclrtDestroyContext(context_), "aclrtDestroyContext failed!"); context_ = nullptr; } } 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) { ACL_CHECK_AND_ABORT(aclrtSetCurrentContext(context_), "aclrtSetCurrentContext failed!"); // 8. 申请输出内存,申请Device内存encodeOutBufferDev_,存放编码后的输出数据 uint32_t outBufferSize= 0; ACL_CHECK_AND_ABORT(acldvppJpegPredictEncSize(encodeInputDesc_, jpegeConfig_, &outBufferSize), "acldvppJpegPredictEncSize failed!"); int ret ; void *encodeOutBufferDev_ = nullptr; ACL_CHECK_AND_ABORT(acldvppMalloc(&encodeOutBufferDev_, outBufferSize), "acldvppJpegPredictEncSize failed!"); bool bRet = false; aclrtStream stream_{nullptr}; aclrtCreateStream(&stream_); do { // 9. 执行异步编码,再调用aclrtSynchronizeStream接口阻塞程序运行,直到指定Stream中的所有任务都完成 ACL_CHECK_AND_ABORT(acldvppJpegEncodeAsync(dvppChannelDesc_, encodeInputDesc_, encodeOutBufferDev_, &outBufferSize, jpegeConfig_, stream_), "acldvppJpegEncodeAsync failed!"); ACL_CHECK_AND_ABORT(aclrtSynchronizeStream(stream_), "aclrtSynchronizeStream failed!"); // 申请Host内存outputHostBuffer void* outputHostBuffer = malloc(outBufferSize); if(outputHostBuffer == nullptr) { LOG_ERROR("malloc failed!"); break; } // 通过aclrtMemcpy接口将Device的处理结果数据传输到Host ACL_CHECK_AND_ABORT(aclrtMemcpy(outputHostBuffer, outBufferSize, encodeOutBufferDev_, outBufferSize, ACL_MEMCPY_DEVICE_TO_HOST), "aclrtMemcpy failed!"); // 数据使用完成后,释放内存 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); if (stream_ != nullptr) { ACL_CHECK_AND_ABORT(aclrtDestroyStream(stream_), "aclrtDestroyStream failed!"); stream_ = nullptr; } // 释放掉输入输出的device内存 (void)acldvppFree(encodeOutBufferDev_); encodeOutBufferDev_ = nullptr; return bRet; }