1 /*
2  * Copyright (C) 2024 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 "post_proc_slr.h"
17 
18 #include <cstdint>
19 #include <memory>
20 #include <unistd.h>
21 #include <vector>
22 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
23 #include "ffrt.h"
24 #endif
25 #include "image_log.h"
26 #include "image_trace.h"
27 #include "image_utils.h"
28 
29 namespace OHOS {
30 namespace Media {
31 using namespace std;
32 
33 constexpr float PI = 3.14159265;
34 constexpr float EPSILON = 1e-6;
35 constexpr int FFRT_THREAD_LIMIT = 8;
36 
GetSLRFactor(float x,int a)37 float GetSLRFactor(float x, int a)
38 {
39     if (a <= 0) {
40         return 1.0f;
41     }
42     if (std::fabs(x) < EPSILON) {
43         return 1.0f;
44     }
45     if (x > a || x < -a) {
46         return 0.0f;
47     }
48 
49     x *= PI;
50     return a * std::sin(x) * std::sin(x / a) / (x * x);
51 }
52 
GetWeights(float coeff,int n)53 SLRWeightMat SLRProc::GetWeights(float coeff, int n)
54 {
55     if (std::fabs(coeff) < EPSILON || coeff < .0f || n <= 0) {
56         return nullptr;
57     }
58     float tao = 1.0f / coeff;
59     int a = std::max(2, static_cast<int>(std::floor(tao))); // 2 max SLR box size
60     SLRWeightMat weights = std::make_shared<SLRWeightVec>(n, std::vector<float>(2 * a, 0));
61     float beta = 1.0f;
62     if (coeff > 0.8999f && coeff < 1.0f) { // 0.8999f adjust low pass filter
63         beta = 1.2f; // 1.2f adjust low pass filter
64     } else if (coeff < 0.9f && coeff > 0.8f) { // 0.9f adjust low pass filter
65         beta = 1.1f; // 1.1f adjust low pass filter
66     }
67     float scale = coeff > 1.0f ? 1.0f : coeff;
68 
69     for (int i = 0; i < n; i++) {
70         float etaf = (i + 0.5) / coeff - 0.5;
71         int eta = std::floor(etaf);
72         for (int k = eta - a + 1; k < eta + a + 1; k++) {
73             float factor = GetSLRFactor(scale / beta * (etaf - k), a);
74             (*weights)[i][k - eta + a - 1] = factor;
75         }
76     }
77     std::vector<float> rowSum(n, 0);
78     for (int i = 0; i < n; i++) {
79         for (int j = 0; j < 2 * a; j++) { // 2 max SLR box size
80             rowSum[i] += (*weights)[i][j];
81         }
82         if (std::fabs(rowSum[i]) < EPSILON) {
83             rowSum[i] = 1.0f; // 1.0f default weight
84         }
85         for (int j = 0; j < 2 * a; j++) { // 2 max SLR box size
86             (*weights)[i][j] /= rowSum[i];
87         }
88     }
89     return weights;
90 }
91 
SLRCheck(const SLRMat & src,const SLRMat & dst,const SLRWeightMat & x,const SLRWeightMat & y)92 bool SLRCheck(const SLRMat &src, const SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y)
93 {
94     if (x == nullptr || y == nullptr) {
95         return false;
96     }
97     if (src.size_.width == 0 || src.size_.height == 0) {
98         return false;
99     }
100     if (dst.size_.width == 0 || dst.size_.height == 0) {
101         return false;
102     }
103     return true;
104 }
105 
SLRCast(float v)106 inline uint32_t SLRCast(float v)
107 {
108     v = std::clamp(v, 0.0f, 255.0f); // 255.0f rgba max value
109     uint32_t uv = static_cast<uint32_t>(v);
110     return uv;
111 }
112 
113 struct SLRSliceKey {
SLRSliceKeyOHOS::Media::SLRSliceKey114     SLRSliceKey(int v1, int v2) : x(v1), y(v2) {}
115     int x;
116     int y;
117 };
118 
SLRBoxCheck(const SLRSliceKey & key,const SLRMat & src,const SLRMat & dst,const SLRWeightMat & x,const SLRWeightMat & y)119 bool SLRBoxCheck(const SLRSliceKey &key, const SLRMat &src, const SLRMat &dst, const SLRWeightMat &x,
120     const SLRWeightMat &y)
121 {
122     if (key.x < 0 || key.y < 0) {
123         IMAGE_LOGE("SLRBoxCheck Key error:%{public}d, %{public}d", key.x, key.y);
124         return false;
125     }
126     uint32_t* srcArr = static_cast<uint32_t*>(src.data_);
127     if (srcArr == nullptr) {
128         IMAGE_LOGE("SLRBoxCheck srcArr null");
129         return false;
130     }
131     uint32_t* dstArr = static_cast<uint32_t*>(dst.data_);
132     if (dstArr == nullptr) {
133         IMAGE_LOGE("SLRBoxCheck dstArr null");
134         return false;
135     }
136     int srcM = src.size_.height, srcN = src.size_.width;
137     int dstM = dst.size_.height, dstN = dst.size_.width;
138     float coeffX = static_cast<float>(dstM) / srcM;
139     float coeffY = static_cast<float>(dstN) / srcN;
140     float taoX = 1 / coeffX;
141     float taoY = 1 / coeffY;
142     int aX = std::max(2, static_cast<int>(std::floor(taoX)));
143     int aY = std::max(2, static_cast<int>(std::floor(taoY))); // 2 default size
144     if (static_cast<int>((*x).size()) < key.y || static_cast<int>((*x)[0].size()) < 2 * aY) { // 2 max slr box size
145         IMAGE_LOGE("SLRBoxCheck h_y error:%{public}zu, %{public}d", (*x).size(), aY);
146         return false;
147     }
148     if (static_cast<int>((*y).size()) < key.x || static_cast<int>((*y)[0].size()) < 2 * aX) { // 2 max slr box size
149         IMAGE_LOGE("SLRBoxCheck h_x error:%{public}zu, %{public}d", (*y).size(), aX);
150         return false;
151     }
152     int dstIndex = key.x * dst.rowStride_ + key.y;
153     int maxDstSize = dstM * dstN;
154     if (dstIndex >= maxDstSize) {
155         IMAGE_LOGE("SLRBoxCheck dst index error:%{public}d, %{public}d", dstIndex, maxDstSize);
156         return false;
157     }
158     return true;
159 }
160 
SLRBox(const SLRSliceKey & key,const SLRMat & src,SLRMat & dst,const SLRWeightMat & x,const SLRWeightMat & y)161 void SLRBox(const SLRSliceKey &key, const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y)
162 {
163     if (!SLRBoxCheck(key, src, dst, x, y)) {
164         return;
165     }
166     uint32_t* srcArr = static_cast<uint32_t*>(src.data_);
167     uint32_t* dstArr = static_cast<uint32_t*>(dst.data_);
168     int srcM = src.size_.height, srcN = src.size_.width, dstM = dst.size_.height, dstN = dst.size_.width;
169     float coeffX = static_cast<float>(dstM) / srcM, coeffY = static_cast<float>(dstN) / srcN;
170     float taoX = 1 / coeffX, taoY = 1 / coeffY;
171     int aX = std::max(2, static_cast<int>(std::floor(taoX)));
172     int aY = std::max(2, static_cast<int>(std::floor(taoY))); // 2 default size
173     int etaI = static_cast<int>((key.x + 0.5) * taoX - 0.5); // 0.5 middle index
174     int etaJ = static_cast<int>((key.y + 0.5) * taoY - 0.5); // 0.5 middle index
175     int rStart = etaI - aX + 1, rEnd = etaI + aX;
176     int cStart = etaJ - aY + 1, cEnd = etaJ + aY;
177     float rgba[4]{ .0f, .0f, .0f, .0f };
178     int maxSrcSize = srcM * srcN;
179     for (int r = rStart; r <= rEnd; ++r) {
180         int nR = min(max(0, r), srcM - 1);
181         for (int c = cStart; c <= cEnd; ++c) {
182             int nC = min(max(0, c), srcN - 1);
183             auto w = (*x)[key.y][c - cStart];
184             w *= (*y)[key.x][r - rStart];
185             int srcIndex = nR *  src.rowStride_ + nC;
186             if (srcIndex < 0 || srcIndex >= maxSrcSize) {
187                 IMAGE_LOGE("SLRBox src index error:%{public}d, %{public}d", srcIndex, maxSrcSize);
188                 return;
189             }
190             uint32_t color = *(srcArr + srcIndex);
191             rgba[0] += ((color >> 24) & 0xFF) * w; // 24 rgba r
192             rgba[1] += ((color >> 16) & 0xFF) * w; // 16 rgba g
193             rgba[2] += ((color >> 8) & 0xFF) * w;  // 2 8 rgba b
194             rgba[3] += (color & 0xFF) * w;         // 3 rgba a
195         }
196     }
197     uint32_t r = SLRCast(rgba[0]), g = SLRCast(rgba[1]), b = SLRCast(rgba[2]), a = SLRCast(rgba[3]); // 2 3 rgba
198     dstArr[key.x * dst.rowStride_ + key.y] = (r << 24) | (g << 16) | (b << 8) | a; // 24 16 8 rgba
199 }
200 
Serial(const SLRMat & src,SLRMat & dst,const SLRWeightMat & x,const SLRWeightMat & y)201 void SLRProc::Serial(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y)
202 {
203     if (!SLRCheck(src, dst, x, y)) {
204         IMAGE_LOGE("SLRProc::Serial param error");
205         return;
206     }
207 
208     int m = dst.size_.height, n = dst.size_.width;
209     for (int i = 0; i < m; i++) {
210         for (int j = 0; j < n; j++) {
211             SLRSliceKey key(i, j);
212             SLRBox(key, src, dst, x, y);
213         }
214     }
215 }
216 
SLRSubtask(const SLRSliceKey & key,const SLRMat & src,SLRMat & dst,const SLRWeightMat & x,const SLRWeightMat & y)217 inline void SLRSubtask(const SLRSliceKey &key, const SLRMat &src, SLRMat &dst,
218     const SLRWeightMat &x, const SLRWeightMat &y)
219 {
220     int start = key.x;
221     int end = key.y;
222     int n = dst.size_.width;
223     for (int i = start; i < end; i++) {
224         for (int j = 0; j < n; j++) {
225             SLRSliceKey boxKey(i, j);
226             SLRBox(boxKey, src, dst, x, y);
227         }
228     }
229 }
230 
Parallel(const SLRMat & src,SLRMat & dst,const SLRWeightMat & x,const SLRWeightMat & y)231 void SLRProc::Parallel(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y)
232 {
233 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
234     if (!SLRCheck(src, dst, x, y)) {
235         IMAGE_LOGE("SLRProc::Parallel param error");
236         return;
237     }
238     const int maxThread = 16; // 16 max thread size
239     int m = dst.size_.height, n = dst.size_.width;
240     int step = m / maxThread;
241     int stepMod = (m % maxThread == 0) ? 1 : 0;
242     std::vector<ffrt::dependence> ffrtHandles;
243     std::vector<ffrt::dependence> ffrtHandles1;
244     for (int k = 0; k < maxThread - stepMod; k++) {
245         int start = k * step;
246         int end = (k + 1) * step;
247         auto func = [&src, &dst, &x, &y, start, end, n] {
248             SLRSliceKey key(start, end);
249             SLRSubtask(key, src, dst, x, y);
250         };
251         auto handler = ffrt::submit_h(func, {}, {}, ffrt::task_attr().qos(5)); // 5 max ffrt qos value
252         if (ffrtHandles.size() < FFRT_THREAD_LIMIT) {
253             ffrtHandles.emplace_back(handler);
254         } else {
255             ffrtHandles1.emplace_back(handler);
256         }
257     }
258 
259     for (int i = (maxThread - stepMod) * step; i < m; i++) {
260         for (int j = 0; j < n; j++) {
261             SLRSliceKey key(i, j);
262             SLRBox(key, src, dst, x, y);
263         }
264     }
265 
266     ffrt::wait(ffrtHandles);
267     ffrt::wait(ffrtHandles1);
268 #else
269     SLRProc::Serial(src, dst, x, y);
270 #endif
271 }
272 } // namespace Media
273 } // namespace OHOS