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 "slide_window_processor.h"
17 
18 #include <memory>
19 
20 #include "aie_log.h"
21 #include "aie_macros.h"
22 #include "aie_retcode_inner.h"
23 #include "securec.h"
24 
25 using namespace OHOS::AI::Feature;
26 
27 namespace {
28     const uint8_t ILLEGAL_BUFFER_MULTIPLIER = 0;
29 }
30 
SlideWindowProcessor()31 SlideWindowProcessor::SlideWindowProcessor()
32     : isInitialized_(false),
33       workBuffer_(nullptr),
34       inputFeature_(nullptr),
35       inType_(UNKNOWN),
36       typeSize_(0),
37       startIndex_(0),
38       initIndex_(0),
39       bufferSize_(0),
40       windowSize_(0),
41       stepSize_(0) {}
42 
~SlideWindowProcessor()43 SlideWindowProcessor::~SlideWindowProcessor()
44 {
45     Release();
46 }
47 
Init(const FeatureProcessorConfig * config)48 int32_t SlideWindowProcessor::Init(const FeatureProcessorConfig *config)
49 {
50     if (isInitialized_) {
51         HILOGE("[SlideWindowProcessor]Fail to init more than once. Release it, then try again");
52         return RETCODE_FAILURE;
53     }
54     if (config == nullptr) {
55         HILOGE("[SlideWindowProcessor]Fail to init with null config");
56         return RETCODE_FAILURE;
57     }
58     auto localConfig = *(static_cast<const SlideWindowProcessorConfig *>(config));
59     if (localConfig.dataType == UNKNOWN) {
60         HILOGE("[SlideWindowProcessor]Fail with unsupported dataType[UNKNOWN]");
61         return RETCODE_FAILURE;
62     }
63     if (localConfig.windowSize < localConfig.stepSize) {
64         HILOGE("[SlideWindowProcessor]Illegal configuration. The stepSize cannot be greater than windowSize");
65         return RETCODE_FAILURE;
66     }
67     if (localConfig.bufferMultiplier == ILLEGAL_BUFFER_MULTIPLIER) {
68         HILOGE("[SlideWindowProcessor]Illegal configuration. The bufferMultiplier cannot be zero");
69         return RETCODE_FAILURE;
70     }
71     inType_ = localConfig.dataType;
72     typeSize_ = CONVERT_DATATYPE_TO_SIZE(inType_);
73     windowSize_ = localConfig.windowSize;
74     stepSize_ = localConfig.stepSize * typeSize_;
75     initIndex_ = (windowSize_ * typeSize_) - stepSize_;
76     startIndex_ = initIndex_;
77     bufferSize_ = (windowSize_ * localConfig.bufferMultiplier) * typeSize_;
78     if (windowSize_ > MAX_SAMPLE_SIZE) {
79         HILOGE("[SlideWindowProcessor]The required memory size is larger than MAX_SAMPLE_SIZE[%zu]",
80             MAX_SAMPLE_SIZE);
81         return RETCODE_FAILURE;
82     }
83     AIE_NEW(workBuffer_, char[bufferSize_]);
84     if (workBuffer_ == nullptr) {
85         HILOGE("[SlideWindowProcessor]Fail to allocate memory for workBuffer");
86         return RETCODE_FAILURE;
87     }
88     (void)memset_s(workBuffer_, bufferSize_, 0, bufferSize_);
89     inputFeature_ = workBuffer_;
90     isInitialized_ = true;
91     return RETCODE_SUCCESS;
92 }
93 
Release()94 void SlideWindowProcessor::Release()
95 {
96     AIE_DELETE_ARRAY(workBuffer_);
97     inputFeature_ = nullptr;
98     isInitialized_ = false;
99 }
100 
Process(const FeatureData & input,FeatureData & output)101 int32_t SlideWindowProcessor::Process(const FeatureData &input, FeatureData &output)
102 {
103     if (!isInitialized_) {
104         HILOGE("[SlideWindowProcessor]Fail to process without successfully init");
105         return RETCODE_FAILURE;
106     }
107     if (input.dataType != inType_) {
108         HILOGE("[SlideWindowProcessor]Fail with unmatched input dataType");
109         return RETCODE_FAILURE;
110     }
111     if (input.data == nullptr || input.size == 0) {
112         HILOGE("[SlideWindowProcessor]Fail with NULL input");
113         return RETCODE_FAILURE;
114     }
115     size_t inputBytes = input.size * typeSize_;
116     if (inputBytes != stepSize_) {
117         HILOGE("[SlideWindowProcessor]Fail with unmatched input dataSize, expected [%zu]", stepSize_ / typeSize_);
118         return RETCODE_FAILURE;
119     }
120     if (output.data != nullptr || output.size != 0) {
121         HILOGE("[SlideWindowProcessor]Fail with non-empty output");
122         return RETCODE_FAILURE;
123     }
124     output.dataType = inType_;
125     // Update the last window by the input data of new window
126     errno_t retCode = memcpy_s(workBuffer_ + startIndex_, bufferSize_ - startIndex_, input.data, inputBytes);
127     if (retCode != EOK) {
128         HILOGE("[SlideWindowProcessor]Fail to copy input data to workBuffer [%d]", retCode);
129         return RETCODE_FAILURE;
130     }
131     output.data = inputFeature_;
132     output.size = windowSize_;
133     startIndex_ += stepSize_;
134     // Slide to the next position
135     inputFeature_ += stepSize_;
136     // Post-processing
137     if (bufferSize_ - startIndex_ < stepSize_) {
138         retCode = memmove_s(workBuffer_, bufferSize_, inputFeature_, initIndex_);
139         if (retCode != EOK) {
140             HILOGE("[SlideWindowProcessor]Fail with memory move. Error code[%d]", retCode);
141             return RETCODE_FAILURE;
142         }
143         startIndex_ = initIndex_;
144         inputFeature_ = workBuffer_;
145     }
146     return RETCODE_SUCCESS;
147 }