1 /*
2 * rkisp_aiq_core.h
3 *
4 * Copyright (c) 2019 Rockchip Corporation
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 "RkLumaCore.h"
20
21 #include <string.h>
22
23 #include "v4l2_buffer_proxy.h"
24 #ifdef RK_SIMULATOR_HW
25 #include "simulator/isp20_hw_simulator.h"
26 #endif
27 #include "common/rk_aiq_comm.h"
28 #include "common/rkisp2-config.h"
29
30 namespace RkCam {
31 #define ISP2X_MIPI_RAW_NORMAL 0
32 #define ISP2X_MIPI_RAW_LONG 1
33 #define ISP2X_MIPI_RAW_SHORT 2
34
35 bool
loop()36 RkLumaCoreThread::loop()
37 {
38 ENTER_ANALYZER_FUNCTION();
39
40 const static int32_t timeout = -1;
41 SmartPtr<VideoBuffer> luma = mStatsQueue.pop (timeout);
42
43 if (!luma.ptr()) {
44 LOGW_ANALYZER("RkLumaCoreThread got empty stats, stop thread");
45 return false;
46 }
47
48 XCamReturn ret = mRkLumaCore->analyze (luma);
49 if (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS)
50 return true;
51
52 LOGE_ANALYZER("RkAiqCoreThread failed to analyze 3a stats");
53
54 EXIT_ANALYZER_FUNCTION();
55
56 return false;
57 }
58
59 uint16_t RkLumaCore::DEFAULT_POOL_SIZE = 20;
60
RkLumaCore()61 RkLumaCore::RkLumaCore()
62 : mState(RK_AIQ_CORE_STATE_INVALID)
63 , mWorkingMode(RK_AIQ_WORKING_MODE_NORMAL)
64 , mCb(NULL)
65 , mRkLumaCoreTh(new RkLumaCoreThread(this))
66 {
67 ENTER_ANALYZER_FUNCTION();
68 EXIT_ANALYZER_FUNCTION();
69 }
70
~RkLumaCore()71 RkLumaCore::~RkLumaCore()
72 {
73 ENTER_ANALYZER_FUNCTION();
74 EXIT_ANALYZER_FUNCTION();
75 }
76
77 XCamReturn
init(const CalibDbV2_LUMA_DETECT_t * lumaCalib)78 RkLumaCore::init(const CalibDbV2_LUMA_DETECT_t* lumaCalib)
79 {
80 ENTER_ANALYZER_FUNCTION();
81
82 if (mState != RK_AIQ_CORE_STATE_INVALID) {
83 LOGE_ANALYZER("wrong state %d\n", mState);
84 return XCAM_RETURN_ERROR_ANALYZER;
85 }
86
87 calib = lumaCalib;
88 LOGD_ANALYZER("en: %d, threshold: %f\n",
89 lumaCalib->luma_detect_en,
90 lumaCalib->mutation_threshold);
91
92 mState = RK_AIQ_CORE_STATE_INITED;
93 return XCAM_RETURN_NO_ERROR;
94
95 EXIT_ANALYZER_FUNCTION();
96 }
97
98 XCamReturn
deInit()99 RkLumaCore::deInit()
100 {
101 ENTER_ANALYZER_FUNCTION();
102
103 if (mState == RK_AIQ_CORE_STATE_STARTED) {
104 LOGE_ANALYZER("wrong state %d\n", mState);
105 return XCAM_RETURN_ERROR_ANALYZER;
106 }
107
108 mState = RK_AIQ_CORE_STATE_INVALID;
109
110 EXIT_ANALYZER_FUNCTION();
111
112 return XCAM_RETURN_NO_ERROR;
113 }
114
115 XCamReturn
start()116 RkLumaCore::start()
117 {
118 ENTER_ANALYZER_FUNCTION();
119
120 if ((mState != RK_AIQ_CORE_STATE_INITED) &&
121 (mState != RK_AIQ_CORE_STATE_PREPARED) &&
122 (mState != RK_AIQ_CORE_STATE_STOPED)) {
123 LOGE_ANALYZER("wrong state %d\n", mState);
124 return XCAM_RETURN_ERROR_ANALYZER;
125 }
126
127 mRkLumaCoreTh->triger_start();
128 mRkLumaCoreTh->start();
129 mState = RK_AIQ_CORE_STATE_STARTED;
130
131 EXIT_ANALYZER_FUNCTION();
132
133 return XCAM_RETURN_NO_ERROR;
134 }
135
136 XCamReturn
stop()137 RkLumaCore::stop()
138 {
139 ENTER_ANALYZER_FUNCTION();
140
141 if (mState != RK_AIQ_CORE_STATE_STARTED) {
142 LOGW_ANALYZER("in state %d\n", mState);
143 return XCAM_RETURN_NO_ERROR;
144 }
145
146 mRkLumaCoreTh->triger_stop();
147 mRkLumaCoreTh->stop();
148 mState = RK_AIQ_CORE_STATE_STOPED;
149
150 EXIT_ANALYZER_FUNCTION();
151
152 return XCAM_RETURN_NO_ERROR;
153 }
154
155
156 XCamReturn
pushStats(SmartPtr<VideoBuffer> & buffer)157 RkLumaCore::pushStats(SmartPtr<VideoBuffer> &buffer)
158 {
159 ENTER_ANALYZER_FUNCTION();
160
161 XCAM_ASSERT(buffer.ptr());
162 mRkLumaCoreTh->push_stats(buffer);
163
164 EXIT_ANALYZER_FUNCTION();
165
166 return XCAM_RETURN_NO_ERROR;
167 }
168
169 XCamReturn
prepare(int mode)170 RkLumaCore::prepare(int mode)
171 {
172 mWorkingMode = mode;
173 return XCAM_RETURN_NO_ERROR;
174 }
175
176 XCamReturn
analyze(const SmartPtr<VideoBuffer> & buffer)177 RkLumaCore::analyze(const SmartPtr<VideoBuffer> &buffer)
178 {
179 rk_aiq_luma_params_t luma_params;
180 memset(&luma_params, 0, sizeof(luma_params));
181 const SmartPtr<V4l2BufferProxy> buf =
182 buffer.dynamic_cast_ptr<V4l2BufferProxy>();
183 #ifdef RK_SIMULATOR_HW
184 rk_sim_isp_v200_luma_t* luma =
185 (rk_sim_isp_v200_luma_t*)(buf->get_v4l2_userptr());
186 LOGD_ANALYZER("lumatest rkaiq get luma(%d): %d\n",
187 luma->valid_luma,
188 luma->image_luma_result.mean_luma[0]);
189
190 if (!mLumaQueueFIFO.is_empty()) {
191 SmartPtr<isp_luma_stat_t> luma_frame_pre = mLumaQueueFIFO.pop();
192 LOGD_ANALYZER("lumatest now pre: %d-%d-%d, datasize: %d\n",
193 luma->image_luma_result.mean_luma[0],
194 luma_frame_pre->mean_luma[0],
195 mLumaQueueFIFO.size());
196 float dluma = float(luma_frame_pre->mean_luma[0] - luma->image_luma_result.mean_luma[0]) /
197 (luma_frame_pre->mean_luma[0] + luma->image_luma_result.mean_luma[0]);
198
199 if (dluma > 0.2 || dluma < -0.2) {
200 luma_params.hdrProcessCnt++;
201 }
202 }
203
204 SmartPtr<isp_luma_stat_t> luma_result = new isp_luma_stat_t();
205 luma_result->mean_luma[0] = luma->image_luma_result.mean_luma[0];
206
207 mLumaQueueFIFO.push(luma_result);
208
209
210 if (mCb)
211 mCb->rkLumaCalcDone(luma_params);
212 #else
213 rkisp_isp2x_luma_buffer* lumaStat =
214 (rkisp_isp2x_luma_buffer*)(buf->get_v4l2_userptr());
215 luma_params.frame_id = lumaStat->frame_id;
216
217 if (calib->fixed_times > 0) {
218 luma_params.hdrProcessCnt = calib->fixed_times - 1;
219 if (luma_params.hdrProcessCnt > 2)
220 luma_params.hdrProcessCnt = 2;
221
222 if (mCb)
223 mCb->rkLumaCalcDone(luma_params);
224
225 return XCAM_RETURN_NO_ERROR;
226 }
227
228
229 int raw_channal = 1;
230 switch (mWorkingMode)
231 {
232 case RK_AIQ_WORKING_MODE_NORMAL:
233 raw_channal = 0;
234 break;
235 case RK_AIQ_ISP_HDR_MODE_2_FRAME_HDR:
236 case RK_AIQ_ISP_HDR_MODE_2_LINE_HDR:
237 raw_channal = 0;
238 break;
239 case RK_AIQ_ISP_HDR_MODE_3_FRAME_HDR:
240 case RK_AIQ_ISP_HDR_MODE_3_LINE_HDR:
241 raw_channal = 1;
242 break;
243 default:
244 raw_channal = 1;
245 break;
246 }
247
248 memcpy(luma_params.luma, lumaStat->luma, sizeof(lumaStat->luma));
249
250 unsigned int mean_luma = 0;
251 for (int i = 0; i < ISP2X_MIPI_LUMA_MEAN_MAX; i++) {
252 mean_luma += lumaStat->luma[raw_channal].exp_mean[i];
253 }
254 mean_luma = mean_luma / ISP2X_MIPI_LUMA_MEAN_MAX;
255
256 if (!mLumaQueueFIFO.is_empty()) {
257 SmartPtr<isp_luma_stat_t> luma_frame_pre = mLumaQueueFIFO.pop();
258
259 float dluma = int(luma_frame_pre->mean_luma[raw_channal] - mean_luma) /
260 float(luma_frame_pre->mean_luma[raw_channal] + mean_luma);
261
262 if (dluma > calib->mutation_threshold_level2 || \
263 dluma < -calib->mutation_threshold_level2)
264 luma_params.hdrProcessCnt = 2;
265 else if (dluma > calib->mutation_threshold || \
266 dluma < -calib->mutation_threshold )
267 luma_params.hdrProcessCnt = 1;
268
269 LOGV_ANALYZER("id(%d) working_mode(0x%x) now-pre: %d-%d, threshold: %f, threshold_level2: %f, "
270 "dluma: %f, hdrProcessCnt: %d, datasize: %d\n",
271 lumaStat->frame_id,
272 mWorkingMode,
273 mean_luma,
274 luma_frame_pre->mean_luma[raw_channal],
275 calib->mutation_threshold,
276 calib->mutation_threshold_level2,
277 dluma,
278 luma_params.hdrProcessCnt,
279 mLumaQueueFIFO.size());
280 }
281
282 SmartPtr<isp_luma_stat_t> luma_result = new isp_luma_stat_t();
283 luma_result->mean_luma[raw_channal] = mean_luma;
284
285 mLumaQueueFIFO.push(luma_result);
286
287 if (mCb)
288 mCb->rkLumaCalcDone(luma_params);
289 #endif
290
291
292 return XCAM_RETURN_NO_ERROR;
293 }
294
295 } //namespace RkCam
296