正在显示
2 个修改的文件
包含
851 行增加
和
0 行删除
app/src/main/jni/olderversion/ndkcamera.cpp
0 → 100644
| 1 | +// Tencent is pleased to support the open source community by making ncnn available. | ||
| 2 | +// | ||
| 3 | +// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. | ||
| 4 | +// | ||
| 5 | +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | ||
| 6 | +// in compliance with the License. You may obtain a copy of the License at | ||
| 7 | +// | ||
| 8 | +// https://opensource.org/licenses/BSD-3-Clause | ||
| 9 | +// | ||
| 10 | +// Unless required by applicable law or agreed to in writing, software distributed | ||
| 11 | +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
| 12 | +// CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
| 13 | +// specific language governing permissions and limitations under the License. | ||
| 14 | + | ||
| 15 | +#include "ndkcamera.h" | ||
| 16 | + | ||
| 17 | +#include <string> | ||
| 18 | + | ||
| 19 | +#include <android/log.h> | ||
| 20 | + | ||
| 21 | +#include <opencv2/core/core.hpp> | ||
| 22 | + | ||
| 23 | +#include "mat.h" | ||
| 24 | + | ||
| 25 | +static void onDisconnected(void* context, ACameraDevice* device) | ||
| 26 | +{ | ||
| 27 | + __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onDisconnected %p", device); | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +static void onError(void* context, ACameraDevice* device, int error) | ||
| 31 | +{ | ||
| 32 | + __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onError %p %d", device, error); | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +static void onImageAvailable(void* context, AImageReader* reader) | ||
| 36 | +{ | ||
| 37 | +// __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onImageAvailable %p", reader); | ||
| 38 | + | ||
| 39 | + AImage* image = 0; | ||
| 40 | + media_status_t status = AImageReader_acquireLatestImage(reader, &image); | ||
| 41 | + | ||
| 42 | + if (status != AMEDIA_OK) | ||
| 43 | + { | ||
| 44 | + // error | ||
| 45 | + return; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + int32_t format; | ||
| 49 | + AImage_getFormat(image, &format); | ||
| 50 | + | ||
| 51 | + // assert format == AIMAGE_FORMAT_YUV_420_888 | ||
| 52 | + | ||
| 53 | + int32_t width = 0; | ||
| 54 | + int32_t height = 0; | ||
| 55 | + AImage_getWidth(image, &width); | ||
| 56 | + AImage_getHeight(image, &height); | ||
| 57 | + | ||
| 58 | + int32_t y_pixelStride = 0; | ||
| 59 | + int32_t u_pixelStride = 0; | ||
| 60 | + int32_t v_pixelStride = 0; | ||
| 61 | + AImage_getPlanePixelStride(image, 0, &y_pixelStride); | ||
| 62 | + AImage_getPlanePixelStride(image, 1, &u_pixelStride); | ||
| 63 | + AImage_getPlanePixelStride(image, 2, &v_pixelStride); | ||
| 64 | + | ||
| 65 | + int32_t y_rowStride = 0; | ||
| 66 | + int32_t u_rowStride = 0; | ||
| 67 | + int32_t v_rowStride = 0; | ||
| 68 | + AImage_getPlaneRowStride(image, 0, &y_rowStride); | ||
| 69 | + AImage_getPlaneRowStride(image, 1, &u_rowStride); | ||
| 70 | + AImage_getPlaneRowStride(image, 2, &v_rowStride); | ||
| 71 | + | ||
| 72 | + uint8_t* y_data = 0; | ||
| 73 | + uint8_t* u_data = 0; | ||
| 74 | + uint8_t* v_data = 0; | ||
| 75 | + int y_len = 0; | ||
| 76 | + int u_len = 0; | ||
| 77 | + int v_len = 0; | ||
| 78 | + AImage_getPlaneData(image, 0, &y_data, &y_len); | ||
| 79 | + AImage_getPlaneData(image, 1, &u_data, &u_len); | ||
| 80 | + AImage_getPlaneData(image, 2, &v_data, &v_len); | ||
| 81 | + | ||
| 82 | + if (u_data == v_data + 1 && v_data == y_data + width * height && y_pixelStride == 1 && u_pixelStride == 2 && v_pixelStride == 2 && y_rowStride == width && u_rowStride == width && v_rowStride == width) | ||
| 83 | + { | ||
| 84 | + // already nv21 :) | ||
| 85 | + ((NdkCamera*)context)->on_image((unsigned char*)y_data, (int)width, (int)height); | ||
| 86 | + } | ||
| 87 | + else | ||
| 88 | + { | ||
| 89 | + // construct nv21 | ||
| 90 | + unsigned char* nv21 = new unsigned char[width * height + width * height / 2]; | ||
| 91 | + { | ||
| 92 | + // Y | ||
| 93 | + unsigned char* yptr = nv21; | ||
| 94 | + for (int y=0; y<height; y++) | ||
| 95 | + { | ||
| 96 | + const unsigned char* y_data_ptr = y_data + y_rowStride * y; | ||
| 97 | + for (int x=0; x<width; x++) | ||
| 98 | + { | ||
| 99 | + yptr[0] = y_data_ptr[0]; | ||
| 100 | + yptr++; | ||
| 101 | + y_data_ptr += y_pixelStride; | ||
| 102 | + } | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + // UV | ||
| 106 | + unsigned char* uvptr = nv21 + width * height; | ||
| 107 | + for (int y=0; y<height/2; y++) | ||
| 108 | + { | ||
| 109 | + const unsigned char* v_data_ptr = v_data + v_rowStride * y; | ||
| 110 | + const unsigned char* u_data_ptr = u_data + u_rowStride * y; | ||
| 111 | + for (int x=0; x<width/2; x++) | ||
| 112 | + { | ||
| 113 | + uvptr[0] = v_data_ptr[0]; | ||
| 114 | + uvptr[1] = u_data_ptr[0]; | ||
| 115 | + uvptr += 2; | ||
| 116 | + v_data_ptr += v_pixelStride; | ||
| 117 | + u_data_ptr += u_pixelStride; | ||
| 118 | + } | ||
| 119 | + } | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + ((NdkCamera*)context)->on_image((unsigned char*)nv21, (int)width, (int)height); | ||
| 123 | + | ||
| 124 | + delete[] nv21; | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + AImage_delete(image); | ||
| 128 | +} | ||
| 129 | + | ||
| 130 | +static void onSessionActive(void* context, ACameraCaptureSession *session) | ||
| 131 | +{ | ||
| 132 | + __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onSessionActive %p", session); | ||
| 133 | +} | ||
| 134 | + | ||
| 135 | +static void onSessionReady(void* context, ACameraCaptureSession *session) | ||
| 136 | +{ | ||
| 137 | + __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onSessionReady %p", session); | ||
| 138 | +} | ||
| 139 | + | ||
| 140 | +static void onSessionClosed(void* context, ACameraCaptureSession *session) | ||
| 141 | +{ | ||
| 142 | + __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onSessionClosed %p", session); | ||
| 143 | +} | ||
| 144 | + | ||
| 145 | +void onCaptureFailed(void* context, ACameraCaptureSession* session, ACaptureRequest* request, ACameraCaptureFailure* failure) | ||
| 146 | +{ | ||
| 147 | + __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onCaptureFailed %p %p %p", session, request, failure); | ||
| 148 | +} | ||
| 149 | + | ||
| 150 | +void onCaptureSequenceCompleted(void* context, ACameraCaptureSession* session, int sequenceId, int64_t frameNumber) | ||
| 151 | +{ | ||
| 152 | + __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onCaptureSequenceCompleted %p %d %ld", session, sequenceId, frameNumber); | ||
| 153 | +} | ||
| 154 | + | ||
| 155 | +void onCaptureSequenceAborted(void* context, ACameraCaptureSession* session, int sequenceId) | ||
| 156 | +{ | ||
| 157 | + __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onCaptureSequenceAborted %p %d", session, sequenceId); | ||
| 158 | +} | ||
| 159 | + | ||
| 160 | +void onCaptureCompleted(void* context, ACameraCaptureSession* session, ACaptureRequest* request, const ACameraMetadata* result) | ||
| 161 | +{ | ||
| 162 | +// __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onCaptureCompleted %p %p %p", session, request, result); | ||
| 163 | +} | ||
| 164 | + | ||
| 165 | +NdkCamera::NdkCamera() | ||
| 166 | +{ | ||
| 167 | + camera_facing = 0; | ||
| 168 | + camera_orientation = 0; | ||
| 169 | + | ||
| 170 | + camera_manager = 0; | ||
| 171 | + camera_device = 0; | ||
| 172 | + image_reader = 0; | ||
| 173 | + image_reader_surface = 0; | ||
| 174 | + image_reader_target = 0; | ||
| 175 | + capture_request = 0; | ||
| 176 | + capture_session_output_container = 0; | ||
| 177 | + capture_session_output = 0; | ||
| 178 | + capture_session = 0; | ||
| 179 | + | ||
| 180 | + | ||
| 181 | + // setup imagereader and its surface | ||
| 182 | + { | ||
| 183 | + AImageReader_new(640, 480, AIMAGE_FORMAT_YUV_420_888, /*maxImages*/2, &image_reader); | ||
| 184 | + | ||
| 185 | + AImageReader_ImageListener listener; | ||
| 186 | + listener.context = this; | ||
| 187 | + listener.onImageAvailable = onImageAvailable; | ||
| 188 | + | ||
| 189 | + AImageReader_setImageListener(image_reader, &listener); | ||
| 190 | + | ||
| 191 | + AImageReader_getWindow(image_reader, &image_reader_surface); | ||
| 192 | + | ||
| 193 | + ANativeWindow_acquire(image_reader_surface); | ||
| 194 | + } | ||
| 195 | +} | ||
| 196 | + | ||
| 197 | +NdkCamera::~NdkCamera() | ||
| 198 | +{ | ||
| 199 | + close(); | ||
| 200 | + | ||
| 201 | + if (image_reader) | ||
| 202 | + { | ||
| 203 | + AImageReader_delete(image_reader); | ||
| 204 | + image_reader = 0; | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | + if (image_reader_surface) | ||
| 208 | + { | ||
| 209 | + ANativeWindow_release(image_reader_surface); | ||
| 210 | + image_reader_surface = 0; | ||
| 211 | + } | ||
| 212 | +} | ||
| 213 | + | ||
| 214 | +int NdkCamera::open(int _camera_facing) | ||
| 215 | +{ | ||
| 216 | + __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "open"); | ||
| 217 | + | ||
| 218 | + camera_facing = _camera_facing; | ||
| 219 | + | ||
| 220 | + camera_manager = ACameraManager_create(); | ||
| 221 | + | ||
| 222 | + // find front camera | ||
| 223 | + std::string camera_id; | ||
| 224 | + { | ||
| 225 | + ACameraIdList* camera_id_list = 0; | ||
| 226 | + ACameraManager_getCameraIdList(camera_manager, &camera_id_list); | ||
| 227 | + | ||
| 228 | + for (int i = 0; i < camera_id_list->numCameras; ++i) | ||
| 229 | + { | ||
| 230 | + const char* id = camera_id_list->cameraIds[i]; | ||
| 231 | + ACameraMetadata* camera_metadata = 0; | ||
| 232 | + ACameraManager_getCameraCharacteristics(camera_manager, id, &camera_metadata); | ||
| 233 | + | ||
| 234 | + // query faceing | ||
| 235 | + acamera_metadata_enum_android_lens_facing_t facing = ACAMERA_LENS_FACING_FRONT; | ||
| 236 | + { | ||
| 237 | + ACameraMetadata_const_entry e = { 0 }; | ||
| 238 | + ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_LENS_FACING, &e); | ||
| 239 | + facing = (acamera_metadata_enum_android_lens_facing_t)e.data.u8[0]; | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + if (camera_facing == 0 && facing != ACAMERA_LENS_FACING_FRONT) | ||
| 243 | + { | ||
| 244 | + ACameraMetadata_free(camera_metadata); | ||
| 245 | + continue; | ||
| 246 | + } | ||
| 247 | + | ||
| 248 | + if (camera_facing == 1 && facing != ACAMERA_LENS_FACING_BACK) | ||
| 249 | + { | ||
| 250 | + ACameraMetadata_free(camera_metadata); | ||
| 251 | + continue; | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + camera_id = id; | ||
| 255 | + | ||
| 256 | + // query orientation | ||
| 257 | + int orientation = 0; | ||
| 258 | + { | ||
| 259 | + ACameraMetadata_const_entry e = { 0 }; | ||
| 260 | + ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SENSOR_ORIENTATION, &e); | ||
| 261 | + | ||
| 262 | + orientation = (int)e.data.i32[0]; | ||
| 263 | + } | ||
| 264 | + | ||
| 265 | + camera_orientation = orientation; | ||
| 266 | + | ||
| 267 | + ACameraMetadata_free(camera_metadata); | ||
| 268 | + | ||
| 269 | + break; | ||
| 270 | + } | ||
| 271 | + | ||
| 272 | + ACameraManager_deleteCameraIdList(camera_id_list); | ||
| 273 | + } | ||
| 274 | + | ||
| 275 | + __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "open %s %d", camera_id.c_str(), camera_orientation); | ||
| 276 | + | ||
| 277 | + // open camera | ||
| 278 | + { | ||
| 279 | + ACameraDevice_StateCallbacks camera_device_state_callbacks; | ||
| 280 | + camera_device_state_callbacks.context = this; | ||
| 281 | + camera_device_state_callbacks.onDisconnected = onDisconnected; | ||
| 282 | + camera_device_state_callbacks.onError = onError; | ||
| 283 | + | ||
| 284 | + ACameraManager_openCamera(camera_manager, camera_id.c_str(), &camera_device_state_callbacks, &camera_device); | ||
| 285 | + } | ||
| 286 | + | ||
| 287 | + // capture request | ||
| 288 | + { | ||
| 289 | + ACameraDevice_createCaptureRequest(camera_device, TEMPLATE_PREVIEW, &capture_request); | ||
| 290 | + | ||
| 291 | + ACameraOutputTarget_create(image_reader_surface, &image_reader_target); | ||
| 292 | + ACaptureRequest_addTarget(capture_request, image_reader_target); | ||
| 293 | + } | ||
| 294 | + | ||
| 295 | + // capture session | ||
| 296 | + { | ||
| 297 | + ACameraCaptureSession_stateCallbacks camera_capture_session_state_callbacks; | ||
| 298 | + camera_capture_session_state_callbacks.context = this; | ||
| 299 | + camera_capture_session_state_callbacks.onActive = onSessionActive; | ||
| 300 | + camera_capture_session_state_callbacks.onReady = onSessionReady; | ||
| 301 | + camera_capture_session_state_callbacks.onClosed = onSessionClosed; | ||
| 302 | + | ||
| 303 | + ACaptureSessionOutputContainer_create(&capture_session_output_container); | ||
| 304 | + | ||
| 305 | + ACaptureSessionOutput_create(image_reader_surface, &capture_session_output); | ||
| 306 | + | ||
| 307 | + ACaptureSessionOutputContainer_add(capture_session_output_container, capture_session_output); | ||
| 308 | + | ||
| 309 | + ACameraDevice_createCaptureSession(camera_device, capture_session_output_container, &camera_capture_session_state_callbacks, &capture_session); | ||
| 310 | + | ||
| 311 | + ACameraCaptureSession_captureCallbacks camera_capture_session_capture_callbacks; | ||
| 312 | + camera_capture_session_capture_callbacks.context = this; | ||
| 313 | + camera_capture_session_capture_callbacks.onCaptureStarted = 0; | ||
| 314 | + camera_capture_session_capture_callbacks.onCaptureProgressed = 0; | ||
| 315 | + camera_capture_session_capture_callbacks.onCaptureCompleted = onCaptureCompleted; | ||
| 316 | + camera_capture_session_capture_callbacks.onCaptureFailed = onCaptureFailed; | ||
| 317 | + camera_capture_session_capture_callbacks.onCaptureSequenceCompleted = onCaptureSequenceCompleted; | ||
| 318 | + camera_capture_session_capture_callbacks.onCaptureSequenceAborted = onCaptureSequenceAborted; | ||
| 319 | + camera_capture_session_capture_callbacks.onCaptureBufferLost = 0; | ||
| 320 | + | ||
| 321 | + ACameraCaptureSession_setRepeatingRequest(capture_session, &camera_capture_session_capture_callbacks, 1, &capture_request, nullptr); | ||
| 322 | + } | ||
| 323 | + | ||
| 324 | + return 0; | ||
| 325 | +} | ||
| 326 | + | ||
| 327 | +void NdkCamera::close() | ||
| 328 | +{ | ||
| 329 | + __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "close"); | ||
| 330 | + | ||
| 331 | + if (capture_session) | ||
| 332 | + { | ||
| 333 | + ACameraCaptureSession_stopRepeating(capture_session); | ||
| 334 | + ACameraCaptureSession_close(capture_session); | ||
| 335 | + capture_session = 0; | ||
| 336 | + } | ||
| 337 | + | ||
| 338 | + if (camera_device) | ||
| 339 | + { | ||
| 340 | + ACameraDevice_close(camera_device); | ||
| 341 | + camera_device = 0; | ||
| 342 | + } | ||
| 343 | + | ||
| 344 | + if (capture_session_output_container) | ||
| 345 | + { | ||
| 346 | + ACaptureSessionOutputContainer_free(capture_session_output_container); | ||
| 347 | + capture_session_output_container = 0; | ||
| 348 | + } | ||
| 349 | + | ||
| 350 | + if (capture_session_output) | ||
| 351 | + { | ||
| 352 | + ACaptureSessionOutput_free(capture_session_output); | ||
| 353 | + capture_session_output = 0; | ||
| 354 | + } | ||
| 355 | + | ||
| 356 | + if (capture_request) | ||
| 357 | + { | ||
| 358 | + ACaptureRequest_free(capture_request); | ||
| 359 | + capture_request = 0; | ||
| 360 | + } | ||
| 361 | + | ||
| 362 | + if (image_reader_target) | ||
| 363 | + { | ||
| 364 | + ACameraOutputTarget_free(image_reader_target); | ||
| 365 | + image_reader_target = 0; | ||
| 366 | + } | ||
| 367 | + | ||
| 368 | + if (camera_manager) | ||
| 369 | + { | ||
| 370 | + ACameraManager_delete(camera_manager); | ||
| 371 | + camera_manager = 0; | ||
| 372 | + } | ||
| 373 | +} | ||
| 374 | + | ||
| 375 | +void NdkCamera::on_image(const cv::Mat& rgb) const | ||
| 376 | +{ | ||
| 377 | +} | ||
| 378 | + | ||
| 379 | +void NdkCamera::on_image(const unsigned char* nv21, int nv21_width, int nv21_height) const | ||
| 380 | +{ | ||
| 381 | + // rotate nv21 | ||
| 382 | + int w = 0; | ||
| 383 | + int h = 0; | ||
| 384 | + int rotate_type = 0; | ||
| 385 | + { | ||
| 386 | + if (camera_orientation == 0) | ||
| 387 | + { | ||
| 388 | + w = nv21_width; | ||
| 389 | + h = nv21_height; | ||
| 390 | + rotate_type = camera_facing == 0 ? 2 : 1; | ||
| 391 | + } | ||
| 392 | + if (camera_orientation == 90) | ||
| 393 | + { | ||
| 394 | + w = nv21_height; | ||
| 395 | + h = nv21_width; | ||
| 396 | + rotate_type = camera_facing == 0 ? 5 : 6; | ||
| 397 | + } | ||
| 398 | + if (camera_orientation == 180) | ||
| 399 | + { | ||
| 400 | + w = nv21_width; | ||
| 401 | + h = nv21_height; | ||
| 402 | + rotate_type = camera_facing == 0 ? 4 : 3; | ||
| 403 | + } | ||
| 404 | + if (camera_orientation == 270) | ||
| 405 | + { | ||
| 406 | + w = nv21_height; | ||
| 407 | + h = nv21_width; | ||
| 408 | + rotate_type = camera_facing == 0 ? 7 : 8; | ||
| 409 | + } | ||
| 410 | + } | ||
| 411 | + | ||
| 412 | + cv::Mat nv21_rotated(h + h / 2, w, CV_8UC1); | ||
| 413 | + ncnn::kanna_rotate_yuv420sp(nv21, nv21_width, nv21_height, nv21_rotated.data, w, h, rotate_type); | ||
| 414 | + | ||
| 415 | + // nv21_rotated to rgb | ||
| 416 | + cv::Mat rgb(h, w, CV_8UC3); | ||
| 417 | + ncnn::yuv420sp2rgb(nv21_rotated.data, w, h, rgb.data); | ||
| 418 | + | ||
| 419 | + on_image(rgb); | ||
| 420 | +} | ||
| 421 | + | ||
| 422 | +static const int NDKCAMERAWINDOW_ID = 233; | ||
| 423 | + | ||
| 424 | +NdkCameraWindow::NdkCameraWindow() : NdkCamera() | ||
| 425 | +{ | ||
| 426 | + sensor_manager = 0; | ||
| 427 | + sensor_event_queue = 0; | ||
| 428 | + accelerometer_sensor = 0; | ||
| 429 | + win = 0; | ||
| 430 | + | ||
| 431 | + accelerometer_orientation = 0; | ||
| 432 | + | ||
| 433 | + // sensor | ||
| 434 | + sensor_manager = ASensorManager_getInstance(); | ||
| 435 | + | ||
| 436 | + accelerometer_sensor = ASensorManager_getDefaultSensor(sensor_manager, ASENSOR_TYPE_ACCELEROMETER); | ||
| 437 | +} | ||
| 438 | + | ||
| 439 | +NdkCameraWindow::~NdkCameraWindow() | ||
| 440 | +{ | ||
| 441 | + if (accelerometer_sensor) | ||
| 442 | + { | ||
| 443 | + ASensorEventQueue_disableSensor(sensor_event_queue, accelerometer_sensor); | ||
| 444 | + accelerometer_sensor = 0; | ||
| 445 | + } | ||
| 446 | + | ||
| 447 | + if (sensor_event_queue) | ||
| 448 | + { | ||
| 449 | + ASensorManager_destroyEventQueue(sensor_manager, sensor_event_queue); | ||
| 450 | + sensor_event_queue = 0; | ||
| 451 | + } | ||
| 452 | + | ||
| 453 | + if (win) | ||
| 454 | + { | ||
| 455 | + ANativeWindow_release(win); | ||
| 456 | + } | ||
| 457 | +} | ||
| 458 | + | ||
| 459 | +void NdkCameraWindow::set_window(ANativeWindow* _win) | ||
| 460 | +{ | ||
| 461 | + if (win) | ||
| 462 | + { | ||
| 463 | + ANativeWindow_release(win); | ||
| 464 | + } | ||
| 465 | + | ||
| 466 | + win = _win; | ||
| 467 | + ANativeWindow_acquire(win); | ||
| 468 | +} | ||
| 469 | + | ||
| 470 | +void NdkCameraWindow::on_image_render(cv::Mat& rgb) const | ||
| 471 | +{ | ||
| 472 | +} | ||
| 473 | + | ||
| 474 | +void NdkCameraWindow::on_image(const unsigned char* nv21, int nv21_width, int nv21_height) const | ||
| 475 | +{ | ||
| 476 | + // resolve orientation from camera_orientation and accelerometer_sensor | ||
| 477 | + { | ||
| 478 | + if (!sensor_event_queue) | ||
| 479 | + { | ||
| 480 | + sensor_event_queue = ASensorManager_createEventQueue(sensor_manager, ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS), NDKCAMERAWINDOW_ID, 0, 0); | ||
| 481 | + | ||
| 482 | + ASensorEventQueue_enableSensor(sensor_event_queue, accelerometer_sensor); | ||
| 483 | + } | ||
| 484 | + | ||
| 485 | + int id = ALooper_pollOnce(0, 0, 0, 0); | ||
| 486 | + if (id == NDKCAMERAWINDOW_ID) | ||
| 487 | + { | ||
| 488 | + ASensorEvent e[8]; | ||
| 489 | + ssize_t num_event = 0; | ||
| 490 | + while (ASensorEventQueue_hasEvents(sensor_event_queue) == 1) | ||
| 491 | + { | ||
| 492 | + num_event = ASensorEventQueue_getEvents(sensor_event_queue, e, 8); | ||
| 493 | + if (num_event < 0) | ||
| 494 | + break; | ||
| 495 | + } | ||
| 496 | + | ||
| 497 | + if (num_event > 0) | ||
| 498 | + { | ||
| 499 | + float acceleration_x = e[num_event - 1].acceleration.x; | ||
| 500 | + float acceleration_y = e[num_event - 1].acceleration.y; | ||
| 501 | + float acceleration_z = e[num_event - 1].acceleration.z; | ||
| 502 | +// __android_log_print(ANDROID_LOG_WARN, "NdkCameraWindow", "x = %f, y = %f, z = %f", x, y, z); | ||
| 503 | + | ||
| 504 | + if (acceleration_y > 7) | ||
| 505 | + { | ||
| 506 | + accelerometer_orientation = 0; | ||
| 507 | + } | ||
| 508 | + if (acceleration_x < -7) | ||
| 509 | + { | ||
| 510 | + accelerometer_orientation = 90; | ||
| 511 | + } | ||
| 512 | + if (acceleration_y < -7) | ||
| 513 | + { | ||
| 514 | + accelerometer_orientation = 180; | ||
| 515 | + } | ||
| 516 | + if (acceleration_x > 7) | ||
| 517 | + { | ||
| 518 | + accelerometer_orientation = 270; | ||
| 519 | + } | ||
| 520 | + } | ||
| 521 | + } | ||
| 522 | + } | ||
| 523 | + | ||
| 524 | + // roi crop and rotate nv21 | ||
| 525 | + int nv21_roi_x = 0; | ||
| 526 | + int nv21_roi_y = 0; | ||
| 527 | + int nv21_roi_w = 0; | ||
| 528 | + int nv21_roi_h = 0; | ||
| 529 | + int roi_x = 0; | ||
| 530 | + int roi_y = 0; | ||
| 531 | + int roi_w = 0; | ||
| 532 | + int roi_h = 0; | ||
| 533 | + int rotate_type = 0; | ||
| 534 | + int render_w = 0; | ||
| 535 | + int render_h = 0; | ||
| 536 | + int render_rotate_type = 0; | ||
| 537 | + { | ||
| 538 | + int win_w = ANativeWindow_getWidth(win); | ||
| 539 | + int win_h = ANativeWindow_getHeight(win); | ||
| 540 | + | ||
| 541 | + if (accelerometer_orientation == 90 || accelerometer_orientation == 270) | ||
| 542 | + { | ||
| 543 | + std::swap(win_w, win_h); | ||
| 544 | + } | ||
| 545 | + | ||
| 546 | + const int final_orientation = (camera_orientation + accelerometer_orientation) % 360; | ||
| 547 | + | ||
| 548 | + if (final_orientation == 0 || final_orientation == 180) | ||
| 549 | + { | ||
| 550 | + if (win_w * nv21_height > win_h * nv21_width) | ||
| 551 | + { | ||
| 552 | + roi_w = nv21_width; | ||
| 553 | + roi_h = (nv21_width * win_h / win_w) / 2 * 2; | ||
| 554 | + roi_x = 0; | ||
| 555 | + roi_y = ((nv21_height - roi_h) / 2) / 2 * 2; | ||
| 556 | + } | ||
| 557 | + else | ||
| 558 | + { | ||
| 559 | + roi_h = nv21_height; | ||
| 560 | + roi_w = (nv21_height * win_w / win_h) / 2 * 2; | ||
| 561 | + roi_x = ((nv21_width - roi_w) / 2) / 2 * 2; | ||
| 562 | + roi_y = 0; | ||
| 563 | + } | ||
| 564 | + | ||
| 565 | + nv21_roi_x = roi_x; | ||
| 566 | + nv21_roi_y = roi_y; | ||
| 567 | + nv21_roi_w = roi_w; | ||
| 568 | + nv21_roi_h = roi_h; | ||
| 569 | + } | ||
| 570 | + if (final_orientation == 90 || final_orientation == 270) | ||
| 571 | + { | ||
| 572 | + if (win_w * nv21_width > win_h * nv21_height) | ||
| 573 | + { | ||
| 574 | + roi_w = nv21_height; | ||
| 575 | + roi_h = (nv21_height * win_h / win_w) / 2 * 2; | ||
| 576 | + roi_x = 0; | ||
| 577 | + roi_y = ((nv21_width - roi_h) / 2) / 2 * 2; | ||
| 578 | + } | ||
| 579 | + else | ||
| 580 | + { | ||
| 581 | + roi_h = nv21_width; | ||
| 582 | + roi_w = (nv21_width * win_w / win_h) / 2 * 2; | ||
| 583 | + roi_x = ((nv21_height - roi_w) / 2) / 2 * 2; | ||
| 584 | + roi_y = 0; | ||
| 585 | + } | ||
| 586 | + | ||
| 587 | + nv21_roi_x = roi_y; | ||
| 588 | + nv21_roi_y = roi_x; | ||
| 589 | + nv21_roi_w = roi_h; | ||
| 590 | + nv21_roi_h = roi_w; | ||
| 591 | + } | ||
| 592 | + | ||
| 593 | + if (camera_facing == 0) | ||
| 594 | + { | ||
| 595 | + if (camera_orientation == 0 && accelerometer_orientation == 0) | ||
| 596 | + { | ||
| 597 | + rotate_type = 2; | ||
| 598 | + } | ||
| 599 | + if (camera_orientation == 0 && accelerometer_orientation == 90) | ||
| 600 | + { | ||
| 601 | + rotate_type = 7; | ||
| 602 | + } | ||
| 603 | + if (camera_orientation == 0 && accelerometer_orientation == 180) | ||
| 604 | + { | ||
| 605 | + rotate_type = 4; | ||
| 606 | + } | ||
| 607 | + if (camera_orientation == 0 && accelerometer_orientation == 270) | ||
| 608 | + { | ||
| 609 | + rotate_type = 5; | ||
| 610 | + } | ||
| 611 | + if (camera_orientation == 90 && accelerometer_orientation == 0) | ||
| 612 | + { | ||
| 613 | + rotate_type = 5; | ||
| 614 | + } | ||
| 615 | + if (camera_orientation == 90 && accelerometer_orientation == 90) | ||
| 616 | + { | ||
| 617 | + rotate_type = 2; | ||
| 618 | + } | ||
| 619 | + if (camera_orientation == 90 && accelerometer_orientation == 180) | ||
| 620 | + { | ||
| 621 | + rotate_type = 7; | ||
| 622 | + } | ||
| 623 | + if (camera_orientation == 90 && accelerometer_orientation == 270) | ||
| 624 | + { | ||
| 625 | + rotate_type = 4; | ||
| 626 | + } | ||
| 627 | + if (camera_orientation == 180 && accelerometer_orientation == 0) | ||
| 628 | + { | ||
| 629 | + rotate_type = 4; | ||
| 630 | + } | ||
| 631 | + if (camera_orientation == 180 && accelerometer_orientation == 90) | ||
| 632 | + { | ||
| 633 | + rotate_type = 5; | ||
| 634 | + } | ||
| 635 | + if (camera_orientation == 180 && accelerometer_orientation == 180) | ||
| 636 | + { | ||
| 637 | + rotate_type = 2; | ||
| 638 | + } | ||
| 639 | + if (camera_orientation == 180 && accelerometer_orientation == 270) | ||
| 640 | + { | ||
| 641 | + rotate_type = 7; | ||
| 642 | + } | ||
| 643 | + if (camera_orientation == 270 && accelerometer_orientation == 0) | ||
| 644 | + { | ||
| 645 | + rotate_type = 7; | ||
| 646 | + } | ||
| 647 | + if (camera_orientation == 270 && accelerometer_orientation == 90) | ||
| 648 | + { | ||
| 649 | + rotate_type = 4; | ||
| 650 | + } | ||
| 651 | + if (camera_orientation == 270 && accelerometer_orientation == 180) | ||
| 652 | + { | ||
| 653 | + rotate_type = 5; | ||
| 654 | + } | ||
| 655 | + if (camera_orientation == 270 && accelerometer_orientation == 270) | ||
| 656 | + { | ||
| 657 | + rotate_type = 2; | ||
| 658 | + } | ||
| 659 | + } | ||
| 660 | + else | ||
| 661 | + { | ||
| 662 | + if (final_orientation == 0) | ||
| 663 | + { | ||
| 664 | + rotate_type = 1; | ||
| 665 | + } | ||
| 666 | + if (final_orientation == 90) | ||
| 667 | + { | ||
| 668 | + rotate_type = 6; | ||
| 669 | + } | ||
| 670 | + if (final_orientation == 180) | ||
| 671 | + { | ||
| 672 | + rotate_type = 3; | ||
| 673 | + } | ||
| 674 | + if (final_orientation == 270) | ||
| 675 | + { | ||
| 676 | + rotate_type = 8; | ||
| 677 | + } | ||
| 678 | + } | ||
| 679 | + | ||
| 680 | + if (accelerometer_orientation == 0) | ||
| 681 | + { | ||
| 682 | + render_w = roi_w; | ||
| 683 | + render_h = roi_h; | ||
| 684 | + render_rotate_type = 1; | ||
| 685 | + } | ||
| 686 | + if (accelerometer_orientation == 90) | ||
| 687 | + { | ||
| 688 | + render_w = roi_h; | ||
| 689 | + render_h = roi_w; | ||
| 690 | + render_rotate_type = 8; | ||
| 691 | + } | ||
| 692 | + if (accelerometer_orientation == 180) | ||
| 693 | + { | ||
| 694 | + render_w = roi_w; | ||
| 695 | + render_h = roi_h; | ||
| 696 | + render_rotate_type = 3; | ||
| 697 | + } | ||
| 698 | + if (accelerometer_orientation == 270) | ||
| 699 | + { | ||
| 700 | + render_w = roi_h; | ||
| 701 | + render_h = roi_w; | ||
| 702 | + render_rotate_type = 6; | ||
| 703 | + } | ||
| 704 | + } | ||
| 705 | + | ||
| 706 | + // crop and rotate nv21 | ||
| 707 | + cv::Mat nv21_croprotated(roi_h + roi_h / 2, roi_w, CV_8UC1); | ||
| 708 | + { | ||
| 709 | + const unsigned char* srcY = nv21 + nv21_roi_y * nv21_width + nv21_roi_x; | ||
| 710 | + unsigned char* dstY = nv21_croprotated.data; | ||
| 711 | + ncnn::kanna_rotate_c1(srcY, nv21_roi_w, nv21_roi_h, nv21_width, dstY, roi_w, roi_h, roi_w, rotate_type); | ||
| 712 | + | ||
| 713 | + const unsigned char* srcUV = nv21 + nv21_width * nv21_height + nv21_roi_y * nv21_width / 2 + nv21_roi_x; | ||
| 714 | + unsigned char* dstUV = nv21_croprotated.data + roi_w * roi_h; | ||
| 715 | + ncnn::kanna_rotate_c2(srcUV, nv21_roi_w / 2, nv21_roi_h / 2, nv21_width, dstUV, roi_w / 2, roi_h / 2, roi_w, rotate_type); | ||
| 716 | + } | ||
| 717 | + | ||
| 718 | + // nv21_croprotated to rgb | ||
| 719 | + cv::Mat rgb(roi_h, roi_w, CV_8UC3); | ||
| 720 | + ncnn::yuv420sp2rgb(nv21_croprotated.data, roi_w, roi_h, rgb.data); | ||
| 721 | + | ||
| 722 | + on_image_render(rgb); | ||
| 723 | + | ||
| 724 | + // rotate to native window orientation | ||
| 725 | + cv::Mat rgb_render(render_h, render_w, CV_8UC3); | ||
| 726 | + ncnn::kanna_rotate_c3(rgb.data, roi_w, roi_h, rgb_render.data, render_w, render_h, render_rotate_type); | ||
| 727 | + | ||
| 728 | + ANativeWindow_setBuffersGeometry(win, render_w, render_h, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM); | ||
| 729 | + | ||
| 730 | + ANativeWindow_Buffer buf; | ||
| 731 | + ANativeWindow_lock(win, &buf, NULL); | ||
| 732 | + | ||
| 733 | + // scale to target size | ||
| 734 | + if (buf.format == AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM || buf.format == AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM) | ||
| 735 | + { | ||
| 736 | + for (int y = 0; y < render_h; y++) | ||
| 737 | + { | ||
| 738 | + const unsigned char* ptr = rgb_render.ptr<const unsigned char>(y); | ||
| 739 | + unsigned char* outptr = (unsigned char*)buf.bits + buf.stride * 4 * y; | ||
| 740 | + | ||
| 741 | + int x = 0; | ||
| 742 | +#if __ARM_NEON | ||
| 743 | + for (; x + 7 < render_w; x += 8) | ||
| 744 | + { | ||
| 745 | + uint8x8x3_t _rgb = vld3_u8(ptr); | ||
| 746 | + uint8x8x4_t _rgba; | ||
| 747 | + _rgba.val[0] = _rgb.val[0]; | ||
| 748 | + _rgba.val[1] = _rgb.val[1]; | ||
| 749 | + _rgba.val[2] = _rgb.val[2]; | ||
| 750 | + _rgba.val[3] = vdup_n_u8(255); | ||
| 751 | + vst4_u8(outptr, _rgba); | ||
| 752 | + | ||
| 753 | + ptr += 24; | ||
| 754 | + outptr += 32; | ||
| 755 | + } | ||
| 756 | +#endif // __ARM_NEON | ||
| 757 | + for (; x < render_w; x++) | ||
| 758 | + { | ||
| 759 | + outptr[0] = ptr[0]; | ||
| 760 | + outptr[1] = ptr[1]; | ||
| 761 | + outptr[2] = ptr[2]; | ||
| 762 | + outptr[3] = 255; | ||
| 763 | + | ||
| 764 | + ptr += 3; | ||
| 765 | + outptr += 4; | ||
| 766 | + } | ||
| 767 | + } | ||
| 768 | + } | ||
| 769 | + | ||
| 770 | + ANativeWindow_unlockAndPost(win); | ||
| 771 | +} |
app/src/main/jni/olderversion/ndkcamera.h
0 → 100644
| 1 | +// Tencent is pleased to support the open source community by making ncnn available. | ||
| 2 | +// | ||
| 3 | +// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. | ||
| 4 | +// | ||
| 5 | +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | ||
| 6 | +// in compliance with the License. You may obtain a copy of the License at | ||
| 7 | +// | ||
| 8 | +// https://opensource.org/licenses/BSD-3-Clause | ||
| 9 | +// | ||
| 10 | +// Unless required by applicable law or agreed to in writing, software distributed | ||
| 11 | +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
| 12 | +// CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
| 13 | +// specific language governing permissions and limitations under the License. | ||
| 14 | + | ||
| 15 | +#ifndef NDKCAMERA_H | ||
| 16 | +#define NDKCAMERA_H | ||
| 17 | + | ||
| 18 | +#include <android/looper.h> | ||
| 19 | +#include <android/native_window.h> | ||
| 20 | +#include <android/sensor.h> | ||
| 21 | +#include <camera/NdkCameraDevice.h> | ||
| 22 | +#include <camera/NdkCameraManager.h> | ||
| 23 | +#include <camera/NdkCameraMetadata.h> | ||
| 24 | +#include <media/NdkImageReader.h> | ||
| 25 | + | ||
| 26 | +#include <opencv2/core/core.hpp> | ||
| 27 | + | ||
| 28 | +class NdkCamera | ||
| 29 | +{ | ||
| 30 | +public: | ||
| 31 | + NdkCamera(); | ||
| 32 | + virtual ~NdkCamera(); | ||
| 33 | + | ||
| 34 | + // facing 0=front 1=back | ||
| 35 | + int open(int camera_facing = 0); | ||
| 36 | + void close(); | ||
| 37 | + | ||
| 38 | + virtual void on_image(const cv::Mat& rgb) const; | ||
| 39 | + | ||
| 40 | + virtual void on_image(const unsigned char* nv21, int nv21_width, int nv21_height) const; | ||
| 41 | + | ||
| 42 | +public: | ||
| 43 | + int camera_facing; | ||
| 44 | + int camera_orientation; | ||
| 45 | + | ||
| 46 | +private: | ||
| 47 | + ACameraManager* camera_manager; | ||
| 48 | + ACameraDevice* camera_device; | ||
| 49 | + AImageReader* image_reader; | ||
| 50 | + ANativeWindow* image_reader_surface; | ||
| 51 | + ACameraOutputTarget* image_reader_target; | ||
| 52 | + ACaptureRequest* capture_request; | ||
| 53 | + ACaptureSessionOutputContainer* capture_session_output_container; | ||
| 54 | + ACaptureSessionOutput* capture_session_output; | ||
| 55 | + ACameraCaptureSession* capture_session; | ||
| 56 | +}; | ||
| 57 | + | ||
| 58 | +class NdkCameraWindow : public NdkCamera | ||
| 59 | +{ | ||
| 60 | +public: | ||
| 61 | + NdkCameraWindow(); | ||
| 62 | + virtual ~NdkCameraWindow(); | ||
| 63 | + | ||
| 64 | + void set_window(ANativeWindow* win); | ||
| 65 | + | ||
| 66 | + virtual void on_image_render(cv::Mat& rgb) const; | ||
| 67 | + | ||
| 68 | + virtual void on_image(const unsigned char* nv21, int nv21_width, int nv21_height) const; | ||
| 69 | + | ||
| 70 | +public: | ||
| 71 | + mutable int accelerometer_orientation; | ||
| 72 | + | ||
| 73 | +private: | ||
| 74 | + ASensorManager* sensor_manager; | ||
| 75 | + mutable ASensorEventQueue* sensor_event_queue; | ||
| 76 | + const ASensor* accelerometer_sensor; | ||
| 77 | + ANativeWindow* win; | ||
| 78 | +}; | ||
| 79 | + | ||
| 80 | +#endif // NDKCAMERA_H |
-
请 注册 或 登录 后发表评论