JpegUtil.cpp
4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <cstdio>
#include <cstdlib>
#include <memory>
#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;
}