xuning

老版本录音实现

  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 +}
  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