1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "type_converter.h"
17
18 #include <algorithm>
19 #include <memory>
20 #include <numeric>
21 #include <vector>
22
23 #include "aie_log.h"
24 #include "aie_macros.h"
25 #include "aie_retcode_inner.h"
26
27 using namespace OHOS::AI::Feature;
28
29 namespace {
30 #define TYPE_CONVERT_ITEMS(input, output, indices) \
31 do { \
32 std::for_each(indices.begin(), indices.end(), [input, output](size_t i) { \
33 output[i] = input[i]; \
34 }); \
35 } while (0)
36 }
37
38 template<typename InType>
DoCast(const InType * inputAddr,size_t inputSize,FeatureData & buffer)39 static int32_t DoCast(const InType *inputAddr, size_t inputSize, FeatureData &buffer)
40 {
41 std::vector<size_t> indices(inputSize);
42 std::iota(indices.begin(), indices.end(), 0);
43 switch (buffer.dataType) {
44 case UINT8: {
45 auto outputAddr = static_cast<uint8_t *>(buffer.data);
46 TYPE_CONVERT_ITEMS(inputAddr, outputAddr, indices);
47 break;
48 }
49 case INT8: {
50 auto outputAddr = static_cast<int8_t *>(buffer.data);
51 TYPE_CONVERT_ITEMS(inputAddr, outputAddr, indices);
52 break;
53 }
54 case UINT16: {
55 auto outputAddr = static_cast<uint16_t *>(buffer.data);
56 TYPE_CONVERT_ITEMS(inputAddr, outputAddr, indices);
57 break;
58 }
59 case INT16: {
60 auto outputAddr = static_cast<int16_t *>(buffer.data);
61 TYPE_CONVERT_ITEMS(inputAddr, outputAddr, indices);
62 break;
63 }
64 case UINT32: {
65 auto outputAddr = static_cast<uint32_t *>(buffer.data);
66 TYPE_CONVERT_ITEMS(inputAddr, outputAddr, indices);
67 break;
68 }
69 case INT32: {
70 auto outputAddr = static_cast<int32_t *>(buffer.data);
71 TYPE_CONVERT_ITEMS(inputAddr, outputAddr, indices);
72 break;
73 }
74 case FLOAT: {
75 auto outputAddr = static_cast<float *>(buffer.data);
76 TYPE_CONVERT_ITEMS(inputAddr, outputAddr, indices);
77 break;
78 }
79 default:
80 return RETCODE_FAILURE;
81 }
82 return RETCODE_SUCCESS;
83 }
84
TypeConverter()85 TypeConverter::TypeConverter(): isInitialized_(false)
86 {
87 workBuffer_ = {
88 .dataType = UNKNOWN,
89 .data = nullptr,
90 .size = 0,
91 };
92 }
93
~TypeConverter()94 TypeConverter::~TypeConverter()
95 {
96 Release();
97 }
98
Init(const FeatureProcessorConfig * config)99 int32_t TypeConverter::Init(const FeatureProcessorConfig *config)
100 {
101 if (isInitialized_) {
102 HILOGE("[TypeConverter]Fail to initialize more than once. Release it, then try again");
103 return RETCODE_FAILURE;
104 }
105 if (config == nullptr) {
106 HILOGE("[TypeConverter]Fail with null config pointer");
107 return RETCODE_FAILURE;
108 }
109 auto localConfig = *(static_cast<const TypeConverterConfig *>(config));
110 if (localConfig.dataType == UNKNOWN) {
111 HILOGE("[TypeConverter]The configured dataType[UNKNOWN] is unsupported");
112 return RETCODE_FAILURE;
113 }
114 workBuffer_.dataType = localConfig.dataType;
115 workBuffer_.size = localConfig.size;
116 uint8_t typeSize = CONVERT_DATATYPE_TO_SIZE(workBuffer_.dataType);
117 size_t bufferSize = workBuffer_.size * typeSize;
118 if (bufferSize > MAX_SAMPLE_SIZE) {
119 HILOGE("[TypeConverter]The required memory size is larger than MAX_SAMPLE_SIZE[%zu]",
120 MAX_SAMPLE_SIZE);
121 return RETCODE_FAILURE;
122 }
123 AIE_NEW(workBuffer_.data, uint8_t[bufferSize]);
124 if (workBuffer_.data == nullptr) {
125 HILOGE("[TypeConverter]Fail to allocate memory for workBuffer");
126 return RETCODE_FAILURE;
127 }
128 isInitialized_ = true;
129 return RETCODE_SUCCESS;
130 }
131
Release()132 void TypeConverter::Release()
133 {
134 if (isInitialized_) {
135 auto bufferAddr = static_cast<uint8_t *>(workBuffer_.data);
136 AIE_DELETE_ARRAY(bufferAddr);
137 isInitialized_ = false;
138 }
139 }
140
Process(const FeatureData & input,FeatureData & output)141 int32_t TypeConverter::Process(const FeatureData &input, FeatureData &output)
142 {
143 if (output.data != nullptr || output.size != 0) {
144 HILOGE("[TypeConverter]Fail with non-empty output");
145 return RETCODE_FAILURE;
146 }
147 if (input.data == nullptr || input.size == 0) {
148 HILOGE("[TypeConverter]Fail to process with nullptr input");
149 return RETCODE_FAILURE;
150 }
151 if (input.size != workBuffer_.size) {
152 HILOGE("[TypeConverter]The input size[%zu] is not equal to the output size[%zu]",
153 input.size, workBuffer_.size);
154 return RETCODE_FAILURE;
155 }
156 if (InnerProcess(input) != RETCODE_SUCCESS) {
157 HILOGE("[TypeConverter]Fail to convert dataType from input to output");
158 return RETCODE_FAILURE;
159 }
160 output.dataType = workBuffer_.dataType;
161 output.data = workBuffer_.data;
162 output.size = workBuffer_.size;
163 return RETCODE_SUCCESS;
164 }
165
InnerProcess(const FeatureData & input)166 int32_t TypeConverter::InnerProcess(const FeatureData &input)
167 {
168 switch (input.dataType) {
169 case UINT8:
170 return DoCast<uint8_t>(static_cast<uint8_t *>(input.data), input.size, workBuffer_);
171 case INT8:
172 return DoCast<int8_t>(static_cast<int8_t *>(input.data), input.size, workBuffer_);
173 case UINT16:
174 return DoCast<uint16_t>(static_cast<uint16_t *>(input.data), input.size, workBuffer_);
175 case INT16:
176 return DoCast<int16_t>(static_cast<int16_t *>(input.data), input.size, workBuffer_);
177 case UINT32:
178 return DoCast<uint32_t>(static_cast<uint32_t *>(input.data), input.size, workBuffer_);
179 case INT32:
180 return DoCast<int32_t>(static_cast<int32_t *>(input.data), input.size, workBuffer_);
181 case FLOAT:
182 return DoCast<float>(static_cast<float *>(input.data), input.size, workBuffer_);
183 default:
184 HILOGE("[TypeConverter]Fail with unknown input type");
185 return RETCODE_FAILURE;
186 }
187 return RETCODE_SUCCESS;
188 }