1 /*
2 * image_processor.cpp - 2D Image Process Hardware Implementation
3 *
4 * Copyright (c) 2021 Rockchip Electronics Co., Ltd
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19 #include "image_processor.h"
20
21 #include <xcam_log.h>
22
23 #include <map>
24 #include <memory>
25 #include <string>
26
27 #ifdef HAS_LIBRGA
28 #ifdef HAS_LIBDL
29 #include <dlfcn.h>
30 #endif
31 #include "rga/im2d.h"
32 #include "rga/rga.h"
33 #endif
34
35 namespace RkCam {
36
37 #ifdef HAS_LIBRGA
38 #define RGA_LIBRARY_NAME "librga.so"
39
40 using fp_imresize_t = int (*)(const rga_buffer_t src, rga_buffer_t dst, double fx, double fy,
41 int interpolation, int sync);
42 using fp_imcrop_t = int (*)(const rga_buffer_t src, rga_buffer_t dst, im_rect rect, int sync);
43 using fp_imcvtcolor_t = int (*)(rga_buffer_t src, rga_buffer_t dst, int sfmt, int dfmt, int mode,
44 int sync);
45 using fp_imrotate_t = int (*)(const rga_buffer_t src, rga_buffer_t dst, int rotation, int sync);
46 using fp_imflip_t = int (*)(const rga_buffer_t src, rga_buffer_t dst, int mode, int sync);
47 using fp_imcopy_t = int (*)(const rga_buffer_t src, rga_buffer_t dst, int sync);
48 using fp_wrapbuffer_virtualaddr_t = rga_buffer_t (*)(void* vir_addr, int width, int height,
49 int wstride, int hstride, int format);
50 using fp_wrapbuffer_physicaladdr_t = rga_buffer_t (*)(void* phy_addr, int width, int height,
51 int wstride, int hstride, int format);
52 using fp_wrapbuffer_fd_t = rga_buffer_t (*)(int fd, int width, int height, int wstride, int hstride,
53 int format);
54
55 struct rga_ops_s {
56 fp_imresize_t imresize_t;
57 fp_imcrop_t imcrop_t;
58 fp_imcvtcolor_t imcvtcolor_t;
59 fp_imrotate_t imrotate_t;
60 fp_imflip_t imflip_t;
61 fp_imcopy_t imcopy_t;
62 fp_wrapbuffer_virtualaddr_t wrapbuffer_virtualaddr_t;
63 fp_wrapbuffer_physicaladdr_t wrapbuffer_physicaladdr_t;
64 fp_wrapbuffer_fd_t wrapbuffer_fd_t;
65 };
66
67 class RGAOperator : public ImageOperator {
68 public:
RGAOperator()69 RGAOperator() : ImageOperator("rga"){};
70
~RGAOperator()71 virtual ~RGAOperator() {
72 #ifdef HAS_LIBDL
73 if (handle_) {
74 dlclose(handle_);
75 }
76 #endif
77 };
78
79 RGAOperator(const RGAOperator&) = delete;
80 RGAOperator& operator=(const RGAOperator&) = delete;
81
WrapFormat(rk_aiq_format_t fmt)82 int WrapFormat(rk_aiq_format_t fmt) {
83 std::map<rk_aiq_format_t, int> rga_format_map = {
84 {RK_PIX_FMT_Y4, RK_FORMAT_Y4},
85 {RK_PIX_FMT_GREY, RK_FORMAT_YCbCr_400},
86 {RK_PIX_FMT_NV12, RK_FORMAT_YCbCr_420_SP},
87 {RK_PIX_FMT_NV21, RK_FORMAT_YCrCb_420_SP},
88 {RK_PIX_FMT_NV16, RK_FORMAT_YCbCr_422_SP},
89 {RK_PIX_FMT_NV61, RK_FORMAT_YCrCb_422_SP},
90 {RK_PIX_FMT_YVYU, RK_FORMAT_YVYU_422},
91 {RK_PIX_FMT_YVU420, RK_FORMAT_YVYU_420},
92 {RK_PIX_FMT_YUYV, RK_FORMAT_YUYV_422},
93 {RK_PIX_FMT_UYVY, RK_FORMAT_UYVY_422},
94 };
95 auto it = rga_format_map.find(fmt);
96 if (it != rga_format_map.end()) {
97 return it->second;
98 }
99 return -1;
100 }
101
resolve_symbles(void)102 XCamReturn resolve_symbles(void) {
103 #ifdef HAS_LIBDL
104 char* error;
105 handle_ = dlopen(RGA_LIBRARY_NAME, RTLD_LAZY);
106 if (!handle_) {
107 LOGE("Failed to dlopen librga.so : %s", dlerror());
108 return XCAM_RETURN_ERROR_UNKNOWN;
109 }
110 dlerror();
111 rga_ops_.wrapbuffer_virtualaddr_t =
112 (fp_wrapbuffer_virtualaddr_t)dlsym(handle_, "wrapbuffer_virtualaddr_t");
113 error = dlerror();
114 if (error != NULL) {
115 LOGE("Failed to resolve symble wrapbuffer_virtualaddr_t: %s", error);
116 }
117
118 rga_ops_.wrapbuffer_physicaladdr_t =
119 (fp_wrapbuffer_physicaladdr_t)dlsym(handle_, "wrapbuffer_physicaladdr_t");
120 error = dlerror();
121 if (error != NULL) {
122 LOGE("Failed to resolve symble wrapbuffer_physicaladdr_t: %s", error);
123 }
124
125 rga_ops_.wrapbuffer_fd_t = (fp_wrapbuffer_fd_t)dlsym(handle_, "wrapbuffer_fd_t");
126 error = dlerror();
127 if (error != NULL) {
128 LOGE("Failed to resolve symble wrapbuffer_fd_t : %s", error);
129 }
130
131 rga_ops_.imresize_t = (fp_imresize_t)dlsym(handle_, "imresize_t");
132 error = dlerror();
133 if (error != NULL) {
134 LOGE("Failed to resolve symble imreize_t : %s", error);
135 }
136
137 rga_ops_.imcrop_t = (fp_imcrop_t)dlsym(handle_, "imcrop_t");
138 error = dlerror();
139 if (error != NULL) {
140 LOGE("Failed to resolve symble imcrop_t: %s", error);
141 }
142
143 rga_ops_.imcvtcolor_t = (fp_imcvtcolor_t)dlsym(handle_, "imcvtcolor_t");
144 error = dlerror();
145 if (error != NULL) {
146 LOGE("Failed to resolve symble imcvtcolor_t : %s", error);
147 }
148
149 rga_ops_.imrotate_t = (fp_imrotate_t)dlsym(handle_, "imrotate_t");
150 error = dlerror();
151 if (error != NULL) {
152 LOGE("Failed to resolve symble imrotete_t : %s", error);
153 }
154
155 rga_ops_.imflip_t = (fp_imflip_t)dlsym(handle_, "imflip_t");
156 error = dlerror();
157 if (error != NULL) {
158 LOGE("Failed to resolve symble imflip_t : %s", error);
159 }
160
161 rga_ops_.imcopy_t = (fp_imcopy_t)dlsym(handle_, "imcopy_t");
162 error = dlerror();
163 if (error != NULL) {
164 LOGE("Failed to resolve symble imcopy_t : %s", error);
165 }
166 #endif // HAS_LIBDL
167
168 return XCAM_RETURN_NO_ERROR;
169 };
170
resize(const img_buffer_t & src,img_buffer_t & dst,double factor_x,double factor_y,int interpolation,int sync)171 virtual XCamReturn resize(const img_buffer_t& src, img_buffer_t& dst, double factor_x,
172 double factor_y, int interpolation, int sync) final {
173 if (rga_ops_.imresize_t) {
174 rga_buffer_t rga_src = rga_ops_.wrapbuffer_fd_t(
175 src.fd, src.width, src.height, src.wstride, src.hstride, WrapFormat(src.format));
176 rga_buffer_t rga_dst = rga_ops_.wrapbuffer_fd_t(
177 dst.fd, dst.width, dst.height, dst.wstride, dst.hstride, WrapFormat(dst.format));
178
179 if (0 > rga_ops_.imresize_t(rga_src, rga_dst, factor_x, factor_y, interpolation, sync)) {
180 return XCAM_RETURN_ERROR_FAILED;
181 }
182
183 return XCAM_RETURN_NO_ERROR;
184 }
185 LOGE("%s : Not implemented", __func__);
186 return XCAM_RETURN_ERROR_UNKNOWN;
187 };
188
crop(const img_buffer_t & src,img_buffer_t & dst,img_rect_t rect,int sync)189 virtual XCamReturn crop(const img_buffer_t& src, img_buffer_t& dst, img_rect_t rect,
190 int sync) final {
191 LOGE("%s : Not implemented", __func__);
192 return XCAM_RETURN_ERROR_UNKNOWN;
193 };
194
cvtcolor(img_buffer_t & src,img_buffer_t & dst,int sfmt,int dfmt,int mode,int sync)195 virtual XCamReturn cvtcolor(img_buffer_t& src, img_buffer_t& dst, int sfmt, int dfmt, int mode,
196 int sync) final {
197 LOGE("%s : Not implemented", __func__);
198 return XCAM_RETURN_ERROR_UNKNOWN;
199 };
200
rotate(const img_buffer_t & src,img_buffer_t & dst,int rotation,int sync)201 virtual XCamReturn rotate(const img_buffer_t& src, img_buffer_t& dst, int rotation,
202 int sync) final {
203 LOGE("%s : Not implemented", __func__);
204 return XCAM_RETURN_ERROR_UNKNOWN;
205 };
206
flip(const img_buffer_t & src,img_buffer_t & dst,int mode,int sync)207 virtual XCamReturn flip(const img_buffer_t& src, img_buffer_t& dst, int mode, int sync) final {
208 LOGE("%s : Not implemented", __func__);
209 return XCAM_RETURN_ERROR_UNKNOWN;
210 };
211
copy(const img_buffer_t & src,img_buffer_t & dst,int sync)212 virtual XCamReturn copy(const img_buffer_t& src, img_buffer_t& dst, int sync) final {
213 LOGE("%s : Not implemented", __func__);
214 return XCAM_RETURN_ERROR_UNKNOWN;
215 };
216
217 private:
218 void* handle_;
219 struct rga_ops_s rga_ops_;
220 };
221 #endif // HAS_LIBRGA
222
ImageOperator(const std::string name)223 ImageOperator::ImageOperator(const std::string name) : name_(name) {}
224
resize(const img_buffer_t & src,img_buffer_t & dst,double fx,double fy,int interpolation,int sync)225 XCamReturn ImageOperator::resize(const img_buffer_t& src, img_buffer_t& dst, double fx, double fy,
226 int interpolation, int sync) {
227 LOGE("%s : Not implemented", __func__);
228 return XCAM_RETURN_ERROR_UNKNOWN;
229 }
230
crop(const img_buffer_t & src,img_buffer_t & dst,img_rect_t rect,int sync)231 XCamReturn ImageOperator::crop(const img_buffer_t& src, img_buffer_t& dst, img_rect_t rect,
232 int sync) {
233 LOGE("%s : Not implemented", __func__);
234 return XCAM_RETURN_ERROR_UNKNOWN;
235 }
236
cvtcolor(img_buffer_t & src,img_buffer_t & dst,int sfmt,int dfmt,int mode,int sync)237 XCamReturn ImageOperator::cvtcolor(img_buffer_t& src, img_buffer_t& dst, int sfmt, int dfmt,
238 int mode, int sync) {
239 LOGE("%s : Not implemented", __func__);
240 return XCAM_RETURN_ERROR_UNKNOWN;
241 }
242
rotate(const img_buffer_t & src,img_buffer_t & dst,int rotation,int sync)243 XCamReturn ImageOperator::rotate(const img_buffer_t& src, img_buffer_t& dst, int rotation,
244 int sync) {
245 LOGE("%s : Not implemented", __func__);
246 return XCAM_RETURN_ERROR_UNKNOWN;
247 }
248
flip(const img_buffer_t & src,img_buffer_t & dst,int mode,int sync)249 XCamReturn ImageOperator::flip(const img_buffer_t& src, img_buffer_t& dst, int mode, int sync) {
250 LOGE("%s : Not implemented", __func__);
251 return XCAM_RETURN_ERROR_UNKNOWN;
252 }
253
copy(const img_buffer_t & src,img_buffer_t & dst,int sync)254 XCamReturn ImageOperator::copy(const img_buffer_t& src, img_buffer_t& dst, int sync) {
255 LOGE("%s : Not implemented", __func__);
256 return XCAM_RETURN_ERROR_UNKNOWN;
257 }
258
set_operator(const std::string & name)259 void ImageProcessor::set_operator(const std::string& name) {
260 if (operator_ != nullptr && !name.compare(operator_->get_name())) {
261 return;
262 }
263 #ifdef HAS_LIBRGA
264 #ifdef HAS_LIBDL
265 if (!name.compare("rga")) {
266 auto ops = std::unique_ptr<RGAOperator>{new RGAOperator};
267 ops->resolve_symbles();
268 operator_ = std::move(ops);
269 }
270 #else
271 #warning "Using RGA without dynamic loading is NOT implemented yet!!!"
272 #endif
273 #endif
274 }
275
resize(const img_buffer_t & src,img_buffer_t & dst,double factor_x,double factor_y)276 XCamReturn ImageProcessor::resize(const img_buffer_t& src, img_buffer_t& dst, double factor_x,
277 double factor_y) {
278 if (operator_) {
279 return operator_->resize(src, dst, factor_x, factor_y);
280 } else {
281 LOGE("%s : Not implemented", __func__);
282 return XCAM_RETURN_ERROR_UNKNOWN;
283 }
284 }
285
crop(const img_buffer_t & src,img_buffer_t & dst,const img_rect_t & rect)286 XCamReturn ImageProcessor::crop(const img_buffer_t& src, img_buffer_t& dst,
287 const img_rect_t& rect) {
288 LOGE("%s : Not implemented", __func__);
289 return XCAM_RETURN_ERROR_UNKNOWN;
290 }
291
292 } // namespace RkCam
293