android13/hardware/rockchip/camera/psl/rkisp2/RKISP2DevImpl.cpp

352 lines
12 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (C) 2017 Intel Corporation.
* Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "RKISP2DevImpl.h"
namespace android {
namespace camera2 {
namespace rkisp2 {
EptzThread::EptzThread()
{
isInit = false;
runnable = true;
}
EptzThread::~EptzThread()
{
runnable = false;
if(isInit){
isInit = false;
rockx_destroy(rockx_handle);
}
mDetectDatas.clear();
nnBufVecs.clear();
}
void EptzThread::setPreviewCfg(int preview_width, int preview_height){
src_width = preview_width;
src_height = preview_height;
}
void EptzThread::EptzInitCfg(int width, int height)
{
ALOGI("rk-debug:new EptzThread initCfg begin");
npu_width = width;
npu_height = height;
nnBufVecs.clear();
mTexUsage = GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_SW_WRITE_OFTEN;
for (int i=0;i<2;i++) {
sp<GraphicBuffer> buf;
if(i == 0)
buf = new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_YCrCb_NV12, mTexUsage);
else
buf = new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_RGBA_8888, mTexUsage);
nnBufVecs.push_back(buf);
}
ALOGI("rk-debug:EptzThread initCfg preview wh[%d %d]", width, height);
RockxInit("/vendor/etc/model/", "/vendor/etc/key.lic");
EptzInit(width, height, width, height);
isInit = true;
ALOGI("rk-debug:new EptzThread initCfg success");
}
void EptzThread::setMode(int mode)
{
ALOGI("rk-debug:EptzThread setEptzMode %d", mode);
eptz_mode = mode;
}
void EptzThread::setOcclusionMode(int mode)
{
ALOGI("rk-debug:EptzThread setOcclusionMode %d", mode);
occlusion_mode = mode;
}
int EptzThread::getMode()
{
return eptz_mode;
}
bool EptzThread::threadLoop(){
static int mode = eptz_mode;
static bool first_flag = true;
static int cnt = 0;
if (!runnable){
usleep(30*1000);
return true;
}
if (!isInit)
EptzInitCfg(src_width, src_height);
if (mode != eptz_mode || first_flag){
first_flag = false;
switch (eptz_mode)
{
case 1:
setEptzMode(1);
mEptzInfo.eptz_fast_move_frame_judge = 5;
mEptzInfo.eptz_zoom_frame_judge = 10;
break;
case 2:
setEptzMode(2);
mEptzInfo.eptz_fast_move_frame_judge = 10;
mEptzInfo.eptz_zoom_frame_judge = 15;
break;
default:
break;
}
mode = eptz_mode;
}
if(!has_img_data){
usleep(60*1000);
return true;
}else{
has_img_data = false;
}
//return true;
sp<GraphicBuffer> buffer = nullptr;
std::unique_lock<std::mutex> lk(mtx_);
if (nnBufVecs.size() > 0) {
buffer = nnBufVecs[0];
}
lk.unlock();
if (buffer != nullptr) {
void* imagedata = nullptr;
buffer->lock(mTexUsage, &imagedata);
if(mode)
RockxDetectFace(imagedata, npu_width, npu_height, ROCKX_PIXEL_FORMAT_YUV420SP_NV12);
if(occlusion_mode && cnt++ % 200 == 0){
int ret = RockxDetectOcclusion(imagedata, npu_width, npu_height, ROCKX_PIXEL_FORMAT_YUV420SP_NV12);
if(ret != -1){
if(1 == ret)
property_set("vendor.camera.occlusion.status", "1");
else
property_set("vendor.camera.occlusion.status", "0");
}
}
buffer->unlock();
// if(cnt == 100){
// FILE* fp = fopen("/data/test.yuv", "wb+");
// if (fp && buffer != nullptr) {
// void* data = nullptr;
// buffer->lock(mTexUsage, &data);
// fwrite(data, 1, npu_width * npu_height * 3 / 2, fp);
// //RockxDetectFace(rockx_handle, npu_width, npu_height, ROCKX_PIXEL_FORMAT_YUV420SP_NV12);
// buffer->unlock();
// LOGD("rk-debug: write buffer to /data/test.yuv ptr=%p", data);
// fclose(fp);
// } else {
// LOGD("rk-debug: fopen %d(%s)", errno, strerror(errno));
// }
// }
}
return true;
}
int EptzThread::RockxInit(char *model_path, char *licence_path){
rockx_ret_t ret = ROCKX_RET_SUCCESS;
rockx_config_t rockx_configs;
memset(&rockx_configs, 0, sizeof(rockx_config_t));
LOGD("rk-debug rockx_add_config ROCKX_CONFIG_DATA_PATH=%s\n", model_path);
#if defined(TARGET_RK3588)
rockx_add_config(&rockx_configs, ROCKX_CONFIG_DATA_PATH, model_path, strlen(model_path));
rockx_add_config(&rockx_configs, ROCKX_CONFIG_LICENCE_KEY_PATH, licence_path, strlen(licence_path));
#else
rockx_add_config(&rockx_configs, ROCKX_CONFIG_DATA_PATH, model_path);
rockx_add_config(&rockx_configs, ROCKX_CONFIG_LICENCE_KEY_PATH, licence_path);
#endif
ret = rockx_create(&rockx_handle, ROCKX_MODULE_FACE_DETECTION_V2_HORIZONTAL, &rockx_configs, sizeof(rockx_config_t));
if (ret != ROCKX_RET_SUCCESS) {
LOGE("rk-debug init rockx module error %d\n", ret);
return ret;
}else{
ALOGI("rk-debug init rockx module success\n");
}
return ret;
}
int EptzThread::RockxDetectFace(void *in_data, int inWidth, int inHeight, int inPixelFmt){
// initial rockx_image_t variable
rockx_image_t input_image;
input_image.width = inWidth;
input_image.height = inHeight;
input_image.data = (unsigned char *)in_data;
input_image.pixel_format = (rockx_pixel_format)inPixelFmt;
// create rockx_face_array_t for store result
rockx_object_array_t face_array;
memset(&face_array, 0, sizeof(rockx_object_array_t));
// detect face
rockx_ret_t ret = rockx_face_detect((rockx_handle_t)rockx_handle, &input_image, &face_array);
if (ret != ROCKX_RET_SUCCESS) {
LOGD("rk-debug rockx_face_detect error %d\n", ret);
return -1;
}
std::unique_lock<std::mutex> lk(face_mtx_);
mDetectDatas.clear();
for(int i = 0; i < face_array.count; i++){
DetectData DetectData;
DetectData.left = face_array.object[i].box.left;
DetectData.top = face_array.object[i].box.top;
DetectData.right = face_array.object[i].box.right;
DetectData.bottom = face_array.object[i].box.bottom;
DetectData.score = face_array.object[i].score;
mDetectDatas.push_back(DetectData);
LOGD("rk-debug rockx_face_detect[%d] ltrb[%d %d %d %d] score[%.2f] \n", ret,
DetectData.left,
DetectData.top,
DetectData.right,
DetectData.bottom,
DetectData.score);
}
lk.unlock();
return 0;
}
int EptzThread::RockxDetectOcclusion(void *in_data, int inWidth, int inHeight, int inPixelFmt){
// initial rockx_image_t variable
rockx_image_t input_image;
input_image.width = inWidth;
input_image.height = inHeight;
input_image.data = (unsigned char *)in_data;
input_image.pixel_format = (rockx_pixel_format)inPixelFmt;
int result = 0;
#ifndef TARGET_RK3588
// detect occlusion
rockx_ret_t ret = rockx_image_detect_occlusion(&input_image, &result);
if (ret != ROCKX_RET_SUCCESS) {
LOGD("rk-debug rockx_face_detect error %d\n", ret);
return -1;
}
#endif
return result;
}
void EptzThread::EptzInit(int mSrcWidth, int mSrcHeight, int mClipWidth, int mClipHeight){
mEptzInfo.eptz_src_width = mSrcWidth;
mEptzInfo.eptz_src_height = mSrcHeight;
mEptzInfo.eptz_dst_width = mSrcWidth;
mEptzInfo.eptz_dst_height = mSrcHeight;
mEptzInfo.camera_dst_width = mClipWidth;
mEptzInfo.camera_dst_height = mClipHeight;
//2K以上sensor建议使用1280x720数据,低于2K使用640x360
mEptzInfo.eptz_npu_width = npu_width;
mEptzInfo.eptz_npu_height = npu_height;
//V2远距离建议0.4V3近距离建议0.6
mEptzInfo.eptz_facedetect_score_shold = 0.40;
mEptzInfo.eptz_zoom_speed = 2;
mEptzInfo.eptz_ratio = 0.3;
mEptzInfo.eptz_fast_move_frame_judge = 3;
mEptzInfo.eptz_zoom_frame_judge = 10;
mEptzInfo.eptz_threshold_x = 100;
mEptzInfo.eptz_threshold_y = 80;
mEptzInfo.eptz_animation = EPTZ_NONLINEAR;
if (mEptzInfo.camera_dst_width >= 1920) {
mEptzInfo.eptz_iterate_x = 10;
mEptzInfo.eptz_iterate_y = 5;
} else if (mEptzInfo.camera_dst_width >= 1280) {
mEptzInfo.eptz_iterate_x = 8;
mEptzInfo.eptz_iterate_y = 4;
} else {
mEptzInfo.eptz_iterate_x = 6;
mEptzInfo.eptz_iterate_y = 3;
}
ALOGI("rk-debug eptz_info src_wh [%d %d] dst_wh[%d %d], threshold_xy[%d %d] "
"iterate_xy[%d %d] \n",
mEptzInfo.eptz_src_width, mEptzInfo.eptz_src_height,
mEptzInfo.eptz_dst_width, mEptzInfo.eptz_dst_height, mEptzInfo.eptz_threshold_x,
mEptzInfo.eptz_threshold_y, mEptzInfo.eptz_iterate_x, mEptzInfo.eptz_iterate_y);
mLastXY[0] = 0;
mLastXY[1] = 0;
mLastXY[2] = mEptzInfo.eptz_dst_width;
mLastXY[3] = mEptzInfo.eptz_dst_height;
eptzConfigInit(&mEptzInfo);
}
void EptzThread::converData(RgaCropScale::Params rgain){
RgaCropScale::Params eptzRgba, eptzout;
//rga conf
eptzRgba.fd = nnBufVecs[1]->handle->data[0];
eptzRgba.fmt = HAL_PIXEL_FORMAT_RGBA_8888;
eptzRgba.mirror = rgain.mirror;
eptzRgba.width = rgain.width;
eptzRgba.height = rgain.height;
eptzRgba.offset_x = rgain.offset_x;
eptzRgba.offset_y = rgain.offset_y;
eptzRgba.width_stride = rgain.width_stride;
eptzRgba.height_stride = rgain.height_stride;
RgaCropScale::CropScaleNV12Or21(&rgain, &eptzRgba);
//dst conf
eptzout.fd = nnBufVecs[0]->handle->data[0];
eptzout.fmt = rgain.fmt;
eptzout.mirror = rgain.mirror;
eptzout.width = rgain.width;
eptzout.height = rgain.height;
eptzout.offset_x = rgain.offset_x;
eptzout.offset_y = rgain.offset_y;
eptzout.width_stride = rgain.width_stride;
eptzout.height_stride = rgain.height_stride;
RgaCropScale::CropScaleNV12Or21(&rgain, &eptzout);
has_img_data = true;
}
void EptzThread::calculateRect(RgaCropScale::Params *rgain){
std::unique_lock<std::mutex> lk(face_mtx_);
if(mDetectDatas.size()>0){
int faceCount = mDetectDatas.size();
EptzAiData eptz_ai_data;
eptz_ai_data.face_data = (FaceData *)malloc(faceCount * sizeof(FaceData));
eptz_ai_data.face_count = faceCount;
if(eptz_ai_data.face_data){
for(int i = 0; i<faceCount; i++){
eptz_ai_data.face_data[i].left = mDetectDatas[i].left;
eptz_ai_data.face_data[i].top = mDetectDatas[i].top;
eptz_ai_data.face_data[i].right = mDetectDatas[i].right;
eptz_ai_data.face_data[i].bottom = mDetectDatas[i].bottom;
eptz_ai_data.face_data[i].score = mDetectDatas[i].score;
}
}
calculateClipRect(&eptz_ai_data, mLastXY, false, 0);
if(eptz_ai_data.face_data)
free(eptz_ai_data.face_data);
}else{
EptzAiData eptz_ai_data;
eptz_ai_data.face_count = 0;
calculateClipRect(&eptz_ai_data, mLastXY, true, 8);
}
lk.unlock();
rgain->fd = nnBufVecs[1]->handle->data[0];
rgain->fmt = HAL_PIXEL_FORMAT_RGBA_8888;
rgain->offset_x = mLastXY[0];
rgain->offset_y = mLastXY[1];
rgain->width = mLastXY[2];
rgain->height = mLastXY[3];
}
} /* namespace rkisp2 */
} /* namespace camera2 */
} /* namespace android */