android_hardware_camera2_legacy_LegacyCameraDevice.cpp revision 31798f33184fd59dd3d3cc55e6373d9f91d220b6
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "Legacy-CameraDevice-JNI" 18// #define LOG_NDEBUG 0 19#include <utils/Log.h> 20#include <utils/Errors.h> 21#include <utils/Trace.h> 22#include <camera/CameraUtils.h> 23 24#include "jni.h" 25#include "JNIHelp.h" 26#include "android_runtime/AndroidRuntime.h" 27#include "android_runtime/android_view_Surface.h" 28#include "android_runtime/android_graphics_SurfaceTexture.h" 29 30#include <gui/Surface.h> 31#include <gui/IGraphicBufferProducer.h> 32#include <ui/GraphicBuffer.h> 33#include <system/window.h> 34#include <hardware/camera3.h> 35#include <system/camera_metadata.h> 36 37#include <stdint.h> 38#include <inttypes.h> 39 40using namespace android; 41 42// fully-qualified class name 43#define CAMERA_DEVICE_CLASS_NAME "android/hardware/camera2/legacy/LegacyCameraDevice" 44#define CAMERA_DEVICE_BUFFER_SLACK 3 45#define DONT_CARE 0 46 47#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) 48 49#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) ) 50 51/** 52 * Convert from RGB 888 to Y'CbCr using the conversion specified in ITU-R BT.601 for 53 * digital RGB with K_b = 0.114, and K_r = 0.299. 54 */ 55static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane, 56 uint8_t* uPlane, uint8_t* vPlane, size_t chromaStep, size_t yStride, size_t chromaStride) { 57 uint8_t R, G, B; 58 size_t index = 0; 59 60 size_t cStrideDiff = chromaStride - width; 61 62 for (size_t j = 0; j < height; j++) { 63 for (size_t i = 0; i < width; i++) { 64 R = rgbBuf[index++]; 65 G = rgbBuf[index++]; 66 B = rgbBuf[index++]; 67 *(yPlane + i) = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16; 68 69 if (j % 2 == 0 && i % 2 == 0){ 70 *uPlane = (( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128; 71 *vPlane = (( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128; 72 uPlane += chromaStep; 73 vPlane += chromaStep; 74 } 75 // Skip alpha 76 index++; 77 } 78 yPlane += yStride; 79 if (j % 2 == 0) { 80 uPlane += cStrideDiff; 81 vPlane += cStrideDiff; 82 } 83 } 84} 85 86static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, android_ycbcr* ycbcr) { 87 size_t cStep = ycbcr->chroma_step; 88 size_t cStride = ycbcr->cstride; 89 size_t yStride = ycbcr->ystride; 90 rgbToYuv420(rgbBuf, width, height, reinterpret_cast<uint8_t*>(ycbcr->y), 91 reinterpret_cast<uint8_t*>(ycbcr->cb), reinterpret_cast<uint8_t*>(ycbcr->cr), 92 cStep, yStride, cStride); 93} 94 95static status_t configureSurface(const sp<ANativeWindow>& anw, 96 int32_t width, 97 int32_t height, 98 int32_t pixelFmt, 99 int32_t maxBufferSlack) { 100 status_t err = NO_ERROR; 101 err = native_window_set_buffers_dimensions(anw.get(), width, height); 102 if (err != NO_ERROR) { 103 ALOGE("%s: Failed to set native window buffer dimensions, error %s (%d).", __FUNCTION__, 104 strerror(-err), err); 105 return err; 106 } 107 108 err = native_window_set_buffers_format(anw.get(), pixelFmt); 109 if (err != NO_ERROR) { 110 ALOGE("%s: Failed to set native window buffer format, error %s (%d).", __FUNCTION__, 111 strerror(-err), err); 112 return err; 113 } 114 115 err = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN); 116 if (err != NO_ERROR) { 117 ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__, 118 strerror(-err), err); 119 return err; 120 } 121 122 int minUndequeuedBuffers; 123 err = anw.get()->query(anw.get(), 124 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 125 &minUndequeuedBuffers); 126 if (err != NO_ERROR) { 127 ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).", 128 __FUNCTION__, strerror(-err), err); 129 return err; 130 } 131 132 ALOGV("%s: Setting buffer count to %d, size to (%dx%d), fmt (0x%x)", __FUNCTION__, 133 maxBufferSlack + 1 + minUndequeuedBuffers, 134 width, height, pixelFmt); 135 err = native_window_set_buffer_count(anw.get(), maxBufferSlack + 1 + minUndequeuedBuffers); 136 if (err != NO_ERROR) { 137 ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__, 138 strerror(-err), err); 139 return err; 140 } 141 return NO_ERROR; 142} 143 144/** 145 * Produce a frame in the given surface. 146 * 147 * Args: 148 * anw - a surface to produce a frame in. 149 * pixelBuffer - image buffer to generate a frame from. 150 * width - width of the pixelBuffer in pixels. 151 * height - height of the pixelBuffer in pixels. 152 * pixelFmt - format of the pixelBuffer, one of: 153 * HAL_PIXEL_FORMAT_YCrCb_420_SP, 154 * HAL_PIXEL_FORMAT_YCbCr_420_888, 155 * HAL_PIXEL_FORMAT_BLOB 156 * bufSize - the size of the pixelBuffer in bytes. 157 */ 158static status_t produceFrame(const sp<ANativeWindow>& anw, 159 uint8_t* pixelBuffer, 160 int32_t bufWidth, // Width of the pixelBuffer 161 int32_t bufHeight, // Height of the pixelBuffer 162 int32_t pixelFmt, // Format of the pixelBuffer 163 int32_t bufSize) { 164 ATRACE_CALL(); 165 status_t err = NO_ERROR; 166 ANativeWindowBuffer* anb; 167 ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)", 168 __FUNCTION__, anw.get(), bufWidth, bufHeight, pixelFmt, bufSize); 169 170 if (anw == 0) { 171 ALOGE("%s: anw must not be NULL", __FUNCTION__); 172 return BAD_VALUE; 173 } else if (pixelBuffer == NULL) { 174 ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__); 175 return BAD_VALUE; 176 } else if (bufWidth < 0) { 177 ALOGE("%s: width must be non-negative", __FUNCTION__); 178 return BAD_VALUE; 179 } else if (bufHeight < 0) { 180 ALOGE("%s: height must be non-negative", __FUNCTION__); 181 return BAD_VALUE; 182 } else if (bufSize < 0) { 183 ALOGE("%s: bufSize must be non-negative", __FUNCTION__); 184 return BAD_VALUE; 185 } 186 187 size_t width = static_cast<size_t>(bufWidth); 188 size_t height = static_cast<size_t>(bufHeight); 189 size_t bufferLength = static_cast<size_t>(bufSize); 190 191 // TODO: Switch to using Surface::lock and Surface::unlockAndPost 192 err = native_window_dequeue_buffer_and_wait(anw.get(), &anb); 193 if (err != NO_ERROR) return err; 194 195 sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false)); 196 uint32_t gBufWidth = buf->getWidth(); 197 uint32_t gBufHeight = buf->getHeight(); 198 if (gBufWidth != width || gBufHeight != height) { 199 ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32 200 ", expecting dimensions %zu x %zu", __FUNCTION__, gBufWidth, gBufHeight, 201 width, height); 202 return BAD_VALUE; 203 } 204 205 int32_t bufFmt = 0; 206 err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &bufFmt); 207 if (err != NO_ERROR) { 208 ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, 209 strerror(-err), err); 210 return err; 211 } 212 213 uint64_t tmpSize = width * height; 214 if (bufFmt != pixelFmt) { 215 if (bufFmt == HAL_PIXEL_FORMAT_RGBA_8888 && pixelFmt == HAL_PIXEL_FORMAT_BLOB) { 216 ALOGV("%s: Using BLOB to RGBA format override.", __FUNCTION__); 217 tmpSize *= 4; 218 } else { 219 ALOGW("%s: Format mismatch in produceFrame: expecting format %#" PRIx32 220 ", but received buffer with format %#" PRIx32, __FUNCTION__, pixelFmt, bufFmt); 221 } 222 } 223 224 if (tmpSize > SIZE_MAX) { 225 ALOGE("%s: Overflow calculating size, buffer with dimens %zu x %zu is absurdly large...", 226 __FUNCTION__, width, height); 227 return BAD_VALUE; 228 } 229 230 size_t totalSizeBytes = tmpSize; 231 232 switch(pixelFmt) { 233 case HAL_PIXEL_FORMAT_YCrCb_420_SP: { 234 if (bufferLength < totalSizeBytes) { 235 ALOGE("%s: PixelBuffer size %zu too small for given dimensions", 236 __FUNCTION__, bufferLength); 237 return BAD_VALUE; 238 } 239 uint8_t* img = NULL; 240 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); 241 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 242 if (err != NO_ERROR) return err; 243 244 uint8_t* yPlane = img; 245 uint8_t* uPlane = img + height * width; 246 uint8_t* vPlane = uPlane + 1; 247 size_t chromaStep = 2; 248 size_t yStride = width; 249 size_t chromaStride = width; 250 251 rgbToYuv420(pixelBuffer, width, height, yPlane, 252 uPlane, vPlane, chromaStep, yStride, chromaStride); 253 break; 254 } 255 case HAL_PIXEL_FORMAT_YV12: { 256 if (bufferLength < totalSizeBytes) { 257 ALOGE("%s: PixelBuffer size %zu too small for given dimensions", 258 __FUNCTION__, bufferLength); 259 return BAD_VALUE; 260 } 261 262 if ((width & 1) || (height & 1)) { 263 ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height); 264 return BAD_VALUE; 265 } 266 267 uint8_t* img = NULL; 268 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); 269 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 270 if (err != NO_ERROR) { 271 ALOGE("%s: Error %s (%d) while locking gralloc buffer for write.", __FUNCTION__, 272 strerror(-err), err); 273 return err; 274 } 275 276 uint32_t stride = buf->getStride(); 277 LOG_ALWAYS_FATAL_IF(stride % 16, "Stride is not 16 pixel aligned %d", stride); 278 279 uint32_t cStride = ALIGN(stride / 2, 16); 280 size_t chromaStep = 1; 281 282 uint8_t* yPlane = img; 283 uint8_t* crPlane = img + static_cast<uint32_t>(height) * stride; 284 uint8_t* cbPlane = crPlane + cStride * static_cast<uint32_t>(height) / 2; 285 286 rgbToYuv420(pixelBuffer, width, height, yPlane, 287 crPlane, cbPlane, chromaStep, stride, cStride); 288 break; 289 } 290 case HAL_PIXEL_FORMAT_YCbCr_420_888: { 291 // Software writes with YCbCr_420_888 format are unsupported 292 // by the gralloc module for now 293 if (bufferLength < totalSizeBytes) { 294 ALOGE("%s: PixelBuffer size %zu too small for given dimensions", 295 __FUNCTION__, bufferLength); 296 return BAD_VALUE; 297 } 298 android_ycbcr ycbcr = android_ycbcr(); 299 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); 300 301 err = buf->lockYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr); 302 if (err != NO_ERROR) { 303 ALOGE("%s: Failed to lock ycbcr buffer, error %s (%d).", __FUNCTION__, 304 strerror(-err), err); 305 return err; 306 } 307 rgbToYuv420(pixelBuffer, width, height, &ycbcr); 308 break; 309 } 310 case HAL_PIXEL_FORMAT_BLOB: { 311 int8_t* img = NULL; 312 struct camera3_jpeg_blob footer = { 313 jpeg_blob_id: CAMERA3_JPEG_BLOB_ID, 314 jpeg_size: (uint32_t)width 315 }; 316 317 size_t totalJpegSize = bufferLength + sizeof(footer); 318 totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble 319 320 if (height != 1) { 321 ALOGE("%s: Invalid height set for JPEG buffer output, %zu", __FUNCTION__, height); 322 return BAD_VALUE; 323 } 324 325 if (totalJpegSize > totalSizeBytes) { 326 ALOGE("%s: Pixel buffer needs size %zu, cannot fit in gralloc buffer of size %zu", 327 __FUNCTION__, totalJpegSize, totalSizeBytes); 328 return BAD_VALUE; 329 } 330 331 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 332 if (err != NO_ERROR) { 333 ALOGE("%s: Failed to lock buffer, error %s (%d).", __FUNCTION__, strerror(-err), 334 err); 335 return err; 336 } 337 338 memcpy(img, pixelBuffer, bufferLength); 339 memcpy(img + totalSizeBytes - sizeof(footer), &footer, sizeof(footer)); 340 break; 341 } 342 default: { 343 ALOGE("%s: Invalid pixel format in produceFrame: %x", __FUNCTION__, pixelFmt); 344 return BAD_VALUE; 345 } 346 } 347 348 ALOGV("%s: Unlock buffer from %p", __FUNCTION__, anw.get()); 349 err = buf->unlock(); 350 if (err != NO_ERROR) { 351 ALOGE("%s: Failed to unlock buffer, error %s (%d).", __FUNCTION__, strerror(-err), err); 352 return err; 353 } 354 355 ALOGV("%s: Queue buffer to %p", __FUNCTION__, anw.get()); 356 err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), /*fenceFd*/-1); 357 if (err != NO_ERROR) { 358 ALOGE("%s: Failed to queue buffer, error %s (%d).", __FUNCTION__, strerror(-err), err); 359 return err; 360 } 361 return NO_ERROR; 362} 363 364static sp<ANativeWindow> getNativeWindow(JNIEnv* env, jobject surface) { 365 sp<ANativeWindow> anw; 366 if (surface) { 367 anw = android_view_Surface_getNativeWindow(env, surface); 368 if (env->ExceptionCheck()) { 369 return NULL; 370 } 371 } else { 372 jniThrowNullPointerException(env, "surface"); 373 return NULL; 374 } 375 if (anw == NULL) { 376 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 377 "Surface had no valid native window."); 378 return NULL; 379 } 380 return anw; 381} 382 383static sp<ANativeWindow> getNativeWindowFromTexture(JNIEnv* env, jobject surfaceTexture) { 384 sp<ANativeWindow> anw; 385 if (surfaceTexture) { 386 anw = android_SurfaceTexture_getNativeWindow(env, surfaceTexture); 387 if (env->ExceptionCheck()) { 388 return NULL; 389 } 390 } else { 391 jniThrowNullPointerException(env, "surfaceTexture"); 392 return NULL; 393 } 394 if (anw == NULL) { 395 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 396 "SurfaceTexture had no valid native window."); 397 return NULL; 398 } 399 return anw; 400} 401 402static sp<Surface> getSurface(JNIEnv* env, jobject surface) { 403 sp<Surface> s; 404 if (surface) { 405 s = android_view_Surface_getSurface(env, surface); 406 if (env->ExceptionCheck()) { 407 return NULL; 408 } 409 } else { 410 jniThrowNullPointerException(env, "surface"); 411 return NULL; 412 } 413 if (s == NULL) { 414 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 415 "Surface had no valid native Surface."); 416 return NULL; 417 } 418 return s; 419} 420 421extern "C" { 422 423static jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) { 424 ALOGV("nativeDetectSurfaceType"); 425 sp<ANativeWindow> anw; 426 if ((anw = getNativeWindow(env, surface)) == NULL) { 427 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 428 return BAD_VALUE; 429 } 430 int32_t fmt = 0; 431 status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt); 432 if(err != NO_ERROR) { 433 ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err), 434 err); 435 return err; 436 } 437 return fmt; 438} 439 440static jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz, 441 jobject surface, jintArray dimens) { 442 ALOGV("nativeGetSurfaceDimens"); 443 444 if (dimens == NULL) { 445 ALOGE("%s: Null dimens argument passed to nativeDetectSurfaceDimens", __FUNCTION__); 446 return BAD_VALUE; 447 } 448 449 if (env->GetArrayLength(dimens) < 2) { 450 ALOGE("%s: Invalid length of dimens argument in nativeDetectSurfaceDimens", __FUNCTION__); 451 return BAD_VALUE; 452 } 453 454 sp<ANativeWindow> anw; 455 if ((anw = getNativeWindow(env, surface)) == NULL) { 456 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 457 return BAD_VALUE; 458 } 459 int32_t dimenBuf[2]; 460 status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf); 461 if(err != NO_ERROR) { 462 ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err), 463 err); 464 return err; 465 } 466 err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1); 467 if(err != NO_ERROR) { 468 ALOGE("%s: Error while querying surface height %s (%d).", __FUNCTION__, strerror(-err), 469 err); 470 return err; 471 } 472 env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf); 473 return NO_ERROR; 474} 475 476static jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz, 477 jobject surfaceTexture, jintArray dimens) { 478 ALOGV("nativeDetectTextureDimens"); 479 sp<ANativeWindow> anw; 480 if ((anw = getNativeWindowFromTexture(env, surfaceTexture)) == NULL) { 481 ALOGE("%s: Could not retrieve native window from SurfaceTexture.", __FUNCTION__); 482 return BAD_VALUE; 483 } 484 485 int32_t dimenBuf[2]; 486 status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf); 487 if(err != NO_ERROR) { 488 ALOGE("%s: Error while querying SurfaceTexture width %s (%d)", __FUNCTION__, 489 strerror(-err), err); 490 return err; 491 } 492 493 err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1); 494 if(err != NO_ERROR) { 495 ALOGE("%s: Error while querying SurfaceTexture height %s (%d)", __FUNCTION__, 496 strerror(-err), err); 497 return err; 498 } 499 500 env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf); 501 if (env->ExceptionCheck()) { 502 return BAD_VALUE; 503 } 504 return NO_ERROR; 505} 506 507static jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface, 508 jint width, jint height, jint pixelFormat) { 509 ALOGV("nativeConfigureSurface"); 510 sp<ANativeWindow> anw; 511 if ((anw = getNativeWindow(env, surface)) == NULL) { 512 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 513 return BAD_VALUE; 514 } 515 status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK); 516 if (err != NO_ERROR) { 517 ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err); 518 return err; 519 } 520 return NO_ERROR; 521} 522 523static jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface, 524 jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) { 525 ALOGV("nativeProduceFrame"); 526 sp<ANativeWindow> anw; 527 528 if ((anw = getNativeWindow(env, surface)) == NULL) { 529 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 530 return BAD_VALUE; 531 } 532 533 if (pixelBuffer == NULL) { 534 jniThrowNullPointerException(env, "pixelBuffer"); 535 return DONT_CARE; 536 } 537 538 int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer)); 539 jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL); 540 541 if (pixels == NULL) { 542 jniThrowNullPointerException(env, "pixels"); 543 return DONT_CARE; 544 } 545 546 status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height, 547 pixelFormat, bufSize); 548 env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT); 549 550 if (err != NO_ERROR) { 551 ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err); 552 return err; 553 } 554 return NO_ERROR; 555} 556 557static jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface, 558 jint pixelFormat) { 559 ALOGV("nativeSetSurfaceType"); 560 sp<ANativeWindow> anw; 561 if ((anw = getNativeWindow(env, surface)) == NULL) { 562 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 563 return BAD_VALUE; 564 } 565 status_t err = native_window_set_buffers_format(anw.get(), pixelFormat); 566 if (err != NO_ERROR) { 567 ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err); 568 return err; 569 } 570 return NO_ERROR; 571} 572 573static jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface, 574 jint width, jint height) { 575 ALOGV("nativeSetSurfaceDimens"); 576 sp<ANativeWindow> anw; 577 if ((anw = getNativeWindow(env, surface)) == NULL) { 578 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 579 return BAD_VALUE; 580 } 581 status_t err = native_window_set_buffers_dimensions(anw.get(), width, height); 582 if (err != NO_ERROR) { 583 ALOGE("%s: Error while setting surface dimens %s (%d).", __FUNCTION__, strerror(-err), err); 584 return err; 585 } 586 587 // WAR - Set user dimensions also to avoid incorrect scaling after TextureView orientation 588 // change. 589 err = native_window_set_buffers_user_dimensions(anw.get(), width, height); 590 if (err != NO_ERROR) { 591 ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err), 592 err); 593 return err; 594 } 595 return NO_ERROR; 596} 597 598static jlong LegacyCameraDevice_nativeGetSurfaceId(JNIEnv* env, jobject thiz, jobject surface) { 599 ALOGV("nativeGetSurfaceId"); 600 sp<Surface> s; 601 if ((s = getSurface(env, surface)) == NULL) { 602 ALOGE("%s: Could not retrieve native Surface from surface.", __FUNCTION__); 603 return 0; 604 } 605 sp<IGraphicBufferProducer> gbp = s->getIGraphicBufferProducer(); 606 if (gbp == NULL) { 607 ALOGE("%s: Could not retrieve IGraphicBufferProducer from surface.", __FUNCTION__); 608 return 0; 609 } 610 sp<IBinder> b = gbp->asBinder(); 611 if (b == NULL) { 612 ALOGE("%s: Could not retrieve IBinder from surface.", __FUNCTION__); 613 return 0; 614 } 615 /* 616 * FIXME: Use better unique ID for surfaces than native IBinder pointer. Fix also in the camera 617 * service (CameraDeviceClient.h). 618 */ 619 return reinterpret_cast<jlong>(b.get()); 620} 621 622static jint LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv* env, jobject thiz, 623 jobject surface, jint facing, jint orientation) { 624 ALOGV("nativeSetSurfaceOrientation"); 625 sp<ANativeWindow> anw; 626 if ((anw = getNativeWindow(env, surface)) == NULL) { 627 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 628 return BAD_VALUE; 629 } 630 631 status_t err = NO_ERROR; 632 CameraMetadata staticMetadata; 633 634 int32_t orientVal = static_cast<int32_t>(orientation); 635 uint8_t facingVal = static_cast<uint8_t>(facing); 636 staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1); 637 staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1); 638 639 int32_t transform = 0; 640 641 if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) { 642 ALOGE("%s: Invalid rotation transform %s (%d)", __FUNCTION__, strerror(-err), 643 err); 644 return err; 645 } 646 647 ALOGV("%s: Setting buffer sticky transform to %d", __FUNCTION__, transform); 648 649 if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) { 650 ALOGE("%s: Unable to configure surface transform, error %s (%d)", __FUNCTION__, 651 strerror(-err), err); 652 return err; 653 } 654 655 return NO_ERROR; 656} 657 658static jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz, jobject surface, 659 jlong timestamp) { 660 ALOGV("nativeSetNextTimestamp"); 661 sp<ANativeWindow> anw; 662 if ((anw = getNativeWindow(env, surface)) == NULL) { 663 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 664 return BAD_VALUE; 665 } 666 667 status_t err = NO_ERROR; 668 669 if ((err = native_window_set_buffers_timestamp(anw.get(), static_cast<int64_t>(timestamp))) != 670 NO_ERROR) { 671 ALOGE("%s: Unable to set surface timestamp, error %s (%d)", __FUNCTION__, strerror(-err), 672 err); 673 return err; 674 } 675 return NO_ERROR; 676} 677 678static jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) { 679 ALOGV("nativeGetJpegFooterSize"); 680 return static_cast<jint>(sizeof(struct camera3_jpeg_blob)); 681} 682 683} // extern "C" 684 685static JNINativeMethod gCameraDeviceMethods[] = { 686 { "nativeDetectSurfaceType", 687 "(Landroid/view/Surface;)I", 688 (void *)LegacyCameraDevice_nativeDetectSurfaceType }, 689 { "nativeDetectSurfaceDimens", 690 "(Landroid/view/Surface;[I)I", 691 (void *)LegacyCameraDevice_nativeDetectSurfaceDimens }, 692 { "nativeConfigureSurface", 693 "(Landroid/view/Surface;III)I", 694 (void *)LegacyCameraDevice_nativeConfigureSurface }, 695 { "nativeProduceFrame", 696 "(Landroid/view/Surface;[BIII)I", 697 (void *)LegacyCameraDevice_nativeProduceFrame }, 698 { "nativeSetSurfaceFormat", 699 "(Landroid/view/Surface;I)I", 700 (void *)LegacyCameraDevice_nativeSetSurfaceFormat }, 701 { "nativeSetSurfaceDimens", 702 "(Landroid/view/Surface;II)I", 703 (void *)LegacyCameraDevice_nativeSetSurfaceDimens }, 704 { "nativeGetSurfaceId", 705 "(Landroid/view/Surface;)J", 706 (void *)LegacyCameraDevice_nativeGetSurfaceId }, 707 { "nativeDetectTextureDimens", 708 "(Landroid/graphics/SurfaceTexture;[I)I", 709 (void *)LegacyCameraDevice_nativeDetectTextureDimens }, 710 { "nativeSetSurfaceOrientation", 711 "(Landroid/view/Surface;II)I", 712 (void *)LegacyCameraDevice_nativeSetSurfaceOrientation }, 713 { "nativeSetNextTimestamp", 714 "(Landroid/view/Surface;J)I", 715 (void *)LegacyCameraDevice_nativeSetNextTimestamp }, 716 { "nativeGetJpegFooterSize", 717 "()I", 718 (void *)LegacyCameraDevice_nativeGetJpegFooterSize }, 719}; 720 721// Get all the required offsets in java class and register native functions 722int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env) 723{ 724 // Register native functions 725 return AndroidRuntime::registerNativeMethods(env, 726 CAMERA_DEVICE_CLASS_NAME, 727 gCameraDeviceMethods, 728 NELEM(gCameraDeviceMethods)); 729} 730 731