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 <nativehelper/JNIHelp.h> 26 #include "core_jni_helpers.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 <gui/IProducerListener.h> 33 #include <ui/GraphicBuffer.h> 34 #include <system/window.h> 35 #include <hardware/camera3.h> 36 #include <system/camera_metadata.h> 37 38 #include <stdint.h> 39 #include <inttypes.h> 40 41 using namespace android; 42 43 // fully-qualified class name 44 #define CAMERA_DEVICE_CLASS_NAME "android/hardware/camera2/legacy/LegacyCameraDevice" 45 #define CAMERA_DEVICE_BUFFER_SLACK 3 46 #define DONT_CARE 0 47 48 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) 49 50 #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) ) 51 52 // Use BAD_VALUE for surface abandoned error 53 #define OVERRIDE_SURFACE_ERROR(err) \ 54 do { \ 55 if (err == -ENODEV) { \ 56 err = BAD_VALUE; \ 57 } \ 58 } while (0) 59 60 #define UPDATE(md, tag, data, size) \ 61 do { \ 62 if ((md).update((tag), (data), (size))) { \ 63 ALOGE("Update " #tag " failed!"); \ 64 return BAD_VALUE; \ 65 } \ 66 } while (0) 67 68 /** 69 * Convert from RGB 888 to Y'CbCr using the conversion specified in JFIF v1.02 70 */ 71 static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane, 72 uint8_t* crPlane, uint8_t* cbPlane, size_t chromaStep, size_t yStride, size_t chromaStride) { 73 uint8_t R, G, B; 74 size_t index = 0; 75 for (size_t j = 0; j < height; j++) { 76 uint8_t* cr = crPlane; 77 uint8_t* cb = cbPlane; 78 uint8_t* y = yPlane; 79 bool jEven = (j & 1) == 0; 80 for (size_t i = 0; i < width; i++) { 81 R = rgbBuf[index++]; 82 G = rgbBuf[index++]; 83 B = rgbBuf[index++]; 84 *y++ = (77 * R + 150 * G + 29 * B) >> 8; 85 if (jEven && (i & 1) == 0) { 86 *cb = (( -43 * R - 85 * G + 128 * B) >> 8) + 128; 87 *cr = (( 128 * R - 107 * G - 21 * B) >> 8) + 128; 88 cr += chromaStep; 89 cb += chromaStep; 90 } 91 // Skip alpha 92 index++; 93 } 94 yPlane += yStride; 95 if (jEven) { 96 crPlane += chromaStride; 97 cbPlane += chromaStride; 98 } 99 } 100 } 101 102 static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, android_ycbcr* ycbcr) { 103 size_t cStep = ycbcr->chroma_step; 104 size_t cStride = ycbcr->cstride; 105 size_t yStride = ycbcr->ystride; 106 ALOGV("%s: yStride is: %zu, cStride is: %zu, cStep is: %zu", __FUNCTION__, yStride, cStride, 107 cStep); 108 rgbToYuv420(rgbBuf, width, height, reinterpret_cast<uint8_t*>(ycbcr->y), 109 reinterpret_cast<uint8_t*>(ycbcr->cr), reinterpret_cast<uint8_t*>(ycbcr->cb), 110 cStep, yStride, cStride); 111 } 112 113 static status_t connectSurface(const sp<Surface>& surface, int32_t maxBufferSlack) { 114 status_t err = NO_ERROR; 115 116 err = surface->connect(NATIVE_WINDOW_API_CAMERA, /*listener*/NULL); 117 if (err != OK) { 118 ALOGE("%s: Unable to connect to surface, error %s (%d).", __FUNCTION__, 119 strerror(-err), err); 120 return err; 121 } 122 123 err = native_window_set_usage(surface.get(), GRALLOC_USAGE_SW_WRITE_OFTEN); 124 if (err != NO_ERROR) { 125 ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__, 126 strerror(-err), err); 127 OVERRIDE_SURFACE_ERROR(err); 128 return err; 129 } 130 131 int minUndequeuedBuffers; 132 err = static_cast<ANativeWindow*>(surface.get())->query(surface.get(), 133 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers); 134 if (err != NO_ERROR) { 135 ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).", 136 __FUNCTION__, strerror(-err), err); 137 OVERRIDE_SURFACE_ERROR(err); 138 return err; 139 } 140 141 ALOGV("%s: Setting buffer count to %d", __FUNCTION__, 142 maxBufferSlack + 1 + minUndequeuedBuffers); 143 err = native_window_set_buffer_count(surface.get(), maxBufferSlack + 1 + minUndequeuedBuffers); 144 if (err != NO_ERROR) { 145 ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__, 146 strerror(-err), err); 147 OVERRIDE_SURFACE_ERROR(err); 148 return err; 149 } 150 return NO_ERROR; 151 } 152 153 /** 154 * Produce a frame in the given surface. 155 * 156 * Args: 157 * anw - a surface to produce a frame in. 158 * pixelBuffer - image buffer to generate a frame from. 159 * width - width of the pixelBuffer in pixels. 160 * height - height of the pixelBuffer in pixels. 161 * pixelFmt - format of the pixelBuffer, one of: 162 * HAL_PIXEL_FORMAT_YCrCb_420_SP, 163 * HAL_PIXEL_FORMAT_YCbCr_420_888, 164 * HAL_PIXEL_FORMAT_BLOB 165 * bufSize - the size of the pixelBuffer in bytes. 166 */ 167 static status_t produceFrame(const sp<ANativeWindow>& anw, 168 uint8_t* pixelBuffer, 169 int32_t bufWidth, // Width of the pixelBuffer 170 int32_t bufHeight, // Height of the pixelBuffer 171 int32_t pixelFmt, // Format of the pixelBuffer 172 int32_t bufSize) { 173 ATRACE_CALL(); 174 status_t err = NO_ERROR; 175 ANativeWindowBuffer* anb; 176 ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)", 177 __FUNCTION__, anw.get(), bufWidth, bufHeight, pixelFmt, bufSize); 178 179 if (anw == 0) { 180 ALOGE("%s: anw must not be NULL", __FUNCTION__); 181 return BAD_VALUE; 182 } else if (pixelBuffer == NULL) { 183 ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__); 184 return BAD_VALUE; 185 } else if (bufWidth < 0) { 186 ALOGE("%s: width must be non-negative", __FUNCTION__); 187 return BAD_VALUE; 188 } else if (bufHeight < 0) { 189 ALOGE("%s: height must be non-negative", __FUNCTION__); 190 return BAD_VALUE; 191 } else if (bufSize < 0) { 192 ALOGE("%s: bufSize must be non-negative", __FUNCTION__); 193 return BAD_VALUE; 194 } 195 196 size_t width = static_cast<size_t>(bufWidth); 197 size_t height = static_cast<size_t>(bufHeight); 198 size_t bufferLength = static_cast<size_t>(bufSize); 199 200 // TODO: Switch to using Surface::lock and Surface::unlockAndPost 201 err = native_window_dequeue_buffer_and_wait(anw.get(), &anb); 202 if (err != NO_ERROR) { 203 ALOGE("%s: Failed to dequeue buffer, error %s (%d).", __FUNCTION__, 204 strerror(-err), err); 205 OVERRIDE_SURFACE_ERROR(err); 206 return err; 207 } 208 209 sp<GraphicBuffer> buf(GraphicBuffer::from(anb)); 210 uint32_t grallocBufWidth = buf->getWidth(); 211 uint32_t grallocBufHeight = buf->getHeight(); 212 uint32_t grallocBufStride = buf->getStride(); 213 if (grallocBufWidth != width || grallocBufHeight != height) { 214 ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32 215 ", expecting dimensions %zu x %zu", __FUNCTION__, grallocBufWidth, 216 grallocBufHeight, width, height); 217 return BAD_VALUE; 218 } 219 220 int32_t bufFmt = 0; 221 err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &bufFmt); 222 if (err != NO_ERROR) { 223 ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, 224 strerror(-err), err); 225 OVERRIDE_SURFACE_ERROR(err); 226 return err; 227 } 228 229 uint64_t tmpSize = (pixelFmt == HAL_PIXEL_FORMAT_BLOB) ? grallocBufWidth : 230 4 * grallocBufHeight * grallocBufWidth; 231 if (bufFmt != pixelFmt) { 232 if (bufFmt == HAL_PIXEL_FORMAT_RGBA_8888 && pixelFmt == HAL_PIXEL_FORMAT_BLOB) { 233 ALOGV("%s: Using BLOB to RGBA format override.", __FUNCTION__); 234 tmpSize = 4 * (grallocBufWidth + grallocBufStride * (grallocBufHeight - 1)); 235 } else { 236 ALOGW("%s: Format mismatch in produceFrame: expecting format %#" PRIx32 237 ", but received buffer with format %#" PRIx32, __FUNCTION__, pixelFmt, bufFmt); 238 } 239 } 240 241 if (tmpSize > SIZE_MAX) { 242 ALOGE("%s: Overflow calculating size, buffer with dimens %zu x %zu is absurdly large...", 243 __FUNCTION__, width, height); 244 return BAD_VALUE; 245 } 246 247 size_t totalSizeBytes = tmpSize; 248 249 ALOGV("%s: Pixel format chosen: %x", __FUNCTION__, pixelFmt); 250 switch(pixelFmt) { 251 case HAL_PIXEL_FORMAT_YCrCb_420_SP: { 252 if (bufferLength < totalSizeBytes) { 253 ALOGE("%s: PixelBuffer size %zu too small for given dimensions", 254 __FUNCTION__, bufferLength); 255 return BAD_VALUE; 256 } 257 uint8_t* img = NULL; 258 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); 259 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 260 if (err != NO_ERROR) return err; 261 262 uint8_t* yPlane = img; 263 uint8_t* uPlane = img + height * width; 264 uint8_t* vPlane = uPlane + 1; 265 size_t chromaStep = 2; 266 size_t yStride = width; 267 size_t chromaStride = width; 268 269 rgbToYuv420(pixelBuffer, width, height, yPlane, 270 uPlane, vPlane, chromaStep, yStride, chromaStride); 271 break; 272 } 273 case HAL_PIXEL_FORMAT_YV12: { 274 if (bufferLength < totalSizeBytes) { 275 ALOGE("%s: PixelBuffer size %zu too small for given dimensions", 276 __FUNCTION__, bufferLength); 277 return BAD_VALUE; 278 } 279 280 if ((width & 1) || (height & 1)) { 281 ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height); 282 return BAD_VALUE; 283 } 284 285 uint8_t* img = NULL; 286 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); 287 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 288 if (err != NO_ERROR) { 289 ALOGE("%s: Error %s (%d) while locking gralloc buffer for write.", __FUNCTION__, 290 strerror(-err), err); 291 return err; 292 } 293 294 uint32_t stride = buf->getStride(); 295 ALOGV("%s: stride is: %" PRIu32, __FUNCTION__, stride); 296 LOG_ALWAYS_FATAL_IF(stride % 16, "Stride is not 16 pixel aligned %d", stride); 297 298 uint32_t cStride = ALIGN(stride / 2, 16); 299 size_t chromaStep = 1; 300 301 uint8_t* yPlane = img; 302 uint8_t* crPlane = img + static_cast<uint32_t>(height) * stride; 303 uint8_t* cbPlane = crPlane + cStride * static_cast<uint32_t>(height) / 2; 304 305 rgbToYuv420(pixelBuffer, width, height, yPlane, 306 crPlane, cbPlane, chromaStep, stride, cStride); 307 break; 308 } 309 case HAL_PIXEL_FORMAT_YCbCr_420_888: { 310 // Software writes with YCbCr_420_888 format are unsupported 311 // by the gralloc module for now 312 if (bufferLength < totalSizeBytes) { 313 ALOGE("%s: PixelBuffer size %zu too small for given dimensions", 314 __FUNCTION__, bufferLength); 315 return BAD_VALUE; 316 } 317 android_ycbcr ycbcr = android_ycbcr(); 318 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); 319 320 err = buf->lockYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr); 321 if (err != NO_ERROR) { 322 ALOGE("%s: Failed to lock ycbcr buffer, error %s (%d).", __FUNCTION__, 323 strerror(-err), err); 324 return err; 325 } 326 rgbToYuv420(pixelBuffer, width, height, &ycbcr); 327 break; 328 } 329 case HAL_PIXEL_FORMAT_BLOB: { 330 int8_t* img = NULL; 331 struct camera3_jpeg_blob footer = { 332 .jpeg_blob_id = CAMERA3_JPEG_BLOB_ID, 333 .jpeg_size = (uint32_t)bufferLength 334 }; 335 336 size_t totalJpegSize = bufferLength + sizeof(footer); 337 totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble 338 339 if (totalJpegSize > totalSizeBytes) { 340 ALOGE("%s: Pixel buffer needs size %zu, cannot fit in gralloc buffer of size %zu", 341 __FUNCTION__, totalJpegSize, totalSizeBytes); 342 return BAD_VALUE; 343 } 344 345 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 346 if (err != NO_ERROR) { 347 ALOGE("%s: Failed to lock buffer, error %s (%d).", __FUNCTION__, strerror(-err), 348 err); 349 return err; 350 } 351 352 memcpy(img, pixelBuffer, bufferLength); 353 memcpy(img + totalSizeBytes - sizeof(footer), &footer, sizeof(footer)); 354 break; 355 } 356 default: { 357 ALOGE("%s: Invalid pixel format in produceFrame: %x", __FUNCTION__, pixelFmt); 358 return BAD_VALUE; 359 } 360 } 361 362 ALOGV("%s: Unlock buffer from %p", __FUNCTION__, anw.get()); 363 err = buf->unlock(); 364 if (err != NO_ERROR) { 365 ALOGE("%s: Failed to unlock buffer, error %s (%d).", __FUNCTION__, strerror(-err), err); 366 return err; 367 } 368 369 ALOGV("%s: Queue buffer to %p", __FUNCTION__, anw.get()); 370 err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), /*fenceFd*/-1); 371 if (err != NO_ERROR) { 372 ALOGE("%s: Failed to queue buffer, error %s (%d).", __FUNCTION__, strerror(-err), err); 373 OVERRIDE_SURFACE_ERROR(err); 374 return err; 375 } 376 return NO_ERROR; 377 } 378 379 static sp<ANativeWindow> getNativeWindow(JNIEnv* env, jobject surface) { 380 sp<ANativeWindow> anw; 381 if (surface) { 382 anw = android_view_Surface_getNativeWindow(env, surface); 383 if (env->ExceptionCheck()) { 384 return NULL; 385 } 386 } else { 387 jniThrowNullPointerException(env, "surface"); 388 return NULL; 389 } 390 if (anw == NULL) { 391 ALOGE("%s: Surface had no valid native window.", __FUNCTION__); 392 return NULL; 393 } 394 return anw; 395 } 396 397 static sp<ANativeWindow> getNativeWindowFromTexture(JNIEnv* env, jobject surfaceTexture) { 398 sp<ANativeWindow> anw; 399 if (surfaceTexture) { 400 anw = android_SurfaceTexture_getNativeWindow(env, surfaceTexture); 401 if (env->ExceptionCheck()) { 402 return NULL; 403 } 404 } else { 405 jniThrowNullPointerException(env, "surfaceTexture"); 406 return NULL; 407 } 408 if (anw == NULL) { 409 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 410 "SurfaceTexture had no valid native window."); 411 return NULL; 412 } 413 return anw; 414 } 415 416 static sp<Surface> getSurface(JNIEnv* env, jobject surface) { 417 sp<Surface> s; 418 if (surface) { 419 s = android_view_Surface_getSurface(env, surface); 420 if (env->ExceptionCheck()) { 421 return NULL; 422 } 423 } else { 424 jniThrowNullPointerException(env, "surface"); 425 return NULL; 426 } 427 if (s == NULL) { 428 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 429 "Surface had no valid native Surface."); 430 return NULL; 431 } 432 return s; 433 } 434 435 extern "C" { 436 437 static jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) { 438 ALOGV("nativeDetectSurfaceType"); 439 sp<ANativeWindow> anw; 440 if ((anw = getNativeWindow(env, surface)) == NULL) { 441 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 442 return BAD_VALUE; 443 } 444 int32_t fmt = 0; 445 status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt); 446 if(err != NO_ERROR) { 447 ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err), 448 err); 449 OVERRIDE_SURFACE_ERROR(err); 450 return err; 451 } 452 return fmt; 453 } 454 455 static jint LegacyCameraDevice_nativeDetectSurfaceDataspace(JNIEnv* env, jobject thiz, jobject surface) { 456 ALOGV("nativeDetectSurfaceDataspace"); 457 sp<ANativeWindow> anw; 458 if ((anw = getNativeWindow(env, surface)) == NULL) { 459 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 460 return BAD_VALUE; 461 } 462 int32_t fmt = 0; 463 status_t err = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE, &fmt); 464 if(err != NO_ERROR) { 465 ALOGE("%s: Error while querying surface dataspace %s (%d).", __FUNCTION__, strerror(-err), 466 err); 467 OVERRIDE_SURFACE_ERROR(err); 468 return err; 469 } 470 return fmt; 471 } 472 473 static jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz, 474 jobject surface, jintArray dimens) { 475 ALOGV("nativeGetSurfaceDimens"); 476 477 if (dimens == NULL) { 478 ALOGE("%s: Null dimens argument passed to nativeDetectSurfaceDimens", __FUNCTION__); 479 return BAD_VALUE; 480 } 481 482 if (env->GetArrayLength(dimens) < 2) { 483 ALOGE("%s: Invalid length of dimens argument in nativeDetectSurfaceDimens", __FUNCTION__); 484 return BAD_VALUE; 485 } 486 487 sp<ANativeWindow> anw; 488 if ((anw = getNativeWindow(env, surface)) == NULL) { 489 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 490 return BAD_VALUE; 491 } 492 int32_t dimenBuf[2]; 493 status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf); 494 if(err != NO_ERROR) { 495 ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err), 496 err); 497 OVERRIDE_SURFACE_ERROR(err); 498 return err; 499 } 500 err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1); 501 if(err != NO_ERROR) { 502 ALOGE("%s: Error while querying surface height %s (%d).", __FUNCTION__, strerror(-err), 503 err); 504 OVERRIDE_SURFACE_ERROR(err); 505 return err; 506 } 507 env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf); 508 return NO_ERROR; 509 } 510 511 static jint LegacyCameraDevice_nativeDetectSurfaceUsageFlags(JNIEnv* env, jobject thiz, 512 jobject surface) { 513 ALOGV("nativeDetectSurfaceUsageFlags"); 514 515 sp<ANativeWindow> anw; 516 if ((anw = getNativeWindow(env, surface)) == NULL) { 517 jniThrowException(env, "java/lang/UnsupportedOperationException;", 518 "Could not retrieve native window from surface."); 519 return BAD_VALUE; 520 } 521 int32_t usage = 0; 522 status_t err = anw->query(anw.get(), NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage); 523 if(err != NO_ERROR) { 524 jniThrowException(env, "java/lang/UnsupportedOperationException;", 525 "Error while querying surface usage bits"); 526 OVERRIDE_SURFACE_ERROR(err); 527 return err; 528 } 529 return usage; 530 } 531 532 static jint LegacyCameraDevice_nativeDisconnectSurface(JNIEnv* env, jobject thiz, 533 jobject surface) { 534 ALOGV("nativeDisconnectSurface"); 535 if (surface == nullptr) return NO_ERROR; 536 537 sp<ANativeWindow> anw; 538 if ((anw = getNativeWindow(env, surface)) == NULL) { 539 ALOGV("Buffer queue has already been abandoned."); 540 return NO_ERROR; 541 } 542 543 status_t err = native_window_api_disconnect(anw.get(), NATIVE_WINDOW_API_CAMERA); 544 if(err != NO_ERROR) { 545 jniThrowException(env, "java/lang/UnsupportedOperationException;", 546 "Error while disconnecting surface"); 547 OVERRIDE_SURFACE_ERROR(err); 548 return err; 549 } 550 return NO_ERROR; 551 } 552 553 static jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz, 554 jobject surfaceTexture, jintArray dimens) { 555 ALOGV("nativeDetectTextureDimens"); 556 sp<ANativeWindow> anw; 557 if ((anw = getNativeWindowFromTexture(env, surfaceTexture)) == NULL) { 558 ALOGE("%s: Could not retrieve native window from SurfaceTexture.", __FUNCTION__); 559 return BAD_VALUE; 560 } 561 562 int32_t dimenBuf[2]; 563 status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf); 564 if(err != NO_ERROR) { 565 ALOGE("%s: Error while querying SurfaceTexture width %s (%d)", __FUNCTION__, 566 strerror(-err), err); 567 OVERRIDE_SURFACE_ERROR(err); 568 return err; 569 } 570 571 err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1); 572 if(err != NO_ERROR) { 573 ALOGE("%s: Error while querying SurfaceTexture height %s (%d)", __FUNCTION__, 574 strerror(-err), err); 575 OVERRIDE_SURFACE_ERROR(err); 576 return err; 577 } 578 579 env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf); 580 if (env->ExceptionCheck()) { 581 return BAD_VALUE; 582 } 583 return NO_ERROR; 584 } 585 586 static jint LegacyCameraDevice_nativeConnectSurface(JNIEnv* env, jobject thiz, jobject surface) { 587 ALOGV("nativeConnectSurface"); 588 sp<Surface> s; 589 if ((s = getSurface(env, surface)) == NULL) { 590 ALOGE("%s: Could not retrieve surface.", __FUNCTION__); 591 return BAD_VALUE; 592 } 593 status_t err = connectSurface(s, CAMERA_DEVICE_BUFFER_SLACK); 594 if (err != NO_ERROR) { 595 ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err); 596 OVERRIDE_SURFACE_ERROR(err); 597 return err; 598 } 599 return NO_ERROR; 600 } 601 602 static jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface, 603 jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) { 604 ALOGV("nativeProduceFrame"); 605 sp<ANativeWindow> anw; 606 607 if ((anw = getNativeWindow(env, surface)) == NULL) { 608 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 609 return BAD_VALUE; 610 } 611 612 if (pixelBuffer == NULL) { 613 jniThrowNullPointerException(env, "pixelBuffer"); 614 return DONT_CARE; 615 } 616 617 int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer)); 618 jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL); 619 620 if (pixels == NULL) { 621 jniThrowNullPointerException(env, "pixels"); 622 return DONT_CARE; 623 } 624 625 status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height, 626 pixelFormat, bufSize); 627 env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT); 628 629 if (err != NO_ERROR) { 630 ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err); 631 return err; 632 } 633 return NO_ERROR; 634 } 635 636 static jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface, 637 jint pixelFormat) { 638 ALOGV("nativeSetSurfaceType"); 639 sp<ANativeWindow> anw; 640 if ((anw = getNativeWindow(env, surface)) == NULL) { 641 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 642 return BAD_VALUE; 643 } 644 status_t err = native_window_set_buffers_format(anw.get(), pixelFormat); 645 if (err != NO_ERROR) { 646 ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err); 647 OVERRIDE_SURFACE_ERROR(err); 648 return err; 649 } 650 return NO_ERROR; 651 } 652 653 static jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface, 654 jint width, jint height) { 655 ALOGV("nativeSetSurfaceDimens"); 656 sp<ANativeWindow> anw; 657 if ((anw = getNativeWindow(env, surface)) == NULL) { 658 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 659 return BAD_VALUE; 660 } 661 662 // Set user dimensions only 663 // The producer dimensions are owned by GL 664 status_t err = native_window_set_buffers_user_dimensions(anw.get(), width, height); 665 if (err != NO_ERROR) { 666 ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err), 667 err); 668 OVERRIDE_SURFACE_ERROR(err); 669 return err; 670 } 671 return NO_ERROR; 672 } 673 674 static jlong LegacyCameraDevice_nativeGetSurfaceId(JNIEnv* env, jobject thiz, jobject surface) { 675 ALOGV("nativeGetSurfaceId"); 676 sp<Surface> s; 677 if ((s = getSurface(env, surface)) == NULL) { 678 ALOGE("%s: Could not retrieve native Surface from surface.", __FUNCTION__); 679 return 0; 680 } 681 sp<IGraphicBufferProducer> gbp = s->getIGraphicBufferProducer(); 682 if (gbp == NULL) { 683 ALOGE("%s: Could not retrieve IGraphicBufferProducer from surface.", __FUNCTION__); 684 return 0; 685 } 686 sp<IBinder> b = IInterface::asBinder(gbp); 687 if (b == NULL) { 688 ALOGE("%s: Could not retrieve IBinder from surface.", __FUNCTION__); 689 return 0; 690 } 691 /* 692 * FIXME: Use better unique ID for surfaces than native IBinder pointer. Fix also in the camera 693 * service (CameraDeviceClient.h). 694 */ 695 return reinterpret_cast<jlong>(b.get()); 696 } 697 698 static jint LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv* env, jobject thiz, 699 jobject surface, jint facing, jint orientation) { 700 ALOGV("nativeSetSurfaceOrientation"); 701 sp<ANativeWindow> anw; 702 if ((anw = getNativeWindow(env, surface)) == NULL) { 703 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 704 return BAD_VALUE; 705 } 706 707 status_t err = NO_ERROR; 708 CameraMetadata staticMetadata; 709 710 int32_t orientVal = static_cast<int32_t>(orientation); 711 uint8_t facingVal = static_cast<uint8_t>(facing); 712 staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1); 713 staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1); 714 715 int32_t transform = 0; 716 717 if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) { 718 ALOGE("%s: Invalid rotation transform %s (%d)", __FUNCTION__, strerror(-err), 719 err); 720 return err; 721 } 722 723 ALOGV("%s: Setting buffer sticky transform to %d", __FUNCTION__, transform); 724 725 if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) { 726 ALOGE("%s: Unable to configure surface transform, error %s (%d)", __FUNCTION__, 727 strerror(-err), err); 728 return err; 729 } 730 731 return NO_ERROR; 732 } 733 734 static jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz, jobject surface, 735 jlong timestamp) { 736 ALOGV("nativeSetNextTimestamp"); 737 sp<ANativeWindow> anw; 738 if ((anw = getNativeWindow(env, surface)) == NULL) { 739 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 740 return BAD_VALUE; 741 } 742 743 status_t err = NO_ERROR; 744 745 if ((err = native_window_set_buffers_timestamp(anw.get(), static_cast<int64_t>(timestamp))) != 746 NO_ERROR) { 747 ALOGE("%s: Unable to set surface timestamp, error %s (%d)", __FUNCTION__, strerror(-err), 748 err); 749 return err; 750 } 751 return NO_ERROR; 752 } 753 754 static jint LegacyCameraDevice_nativeSetScalingMode(JNIEnv* env, jobject thiz, jobject surface, 755 jint mode) { 756 ALOGV("nativeSetScalingMode"); 757 sp<ANativeWindow> anw; 758 if ((anw = getNativeWindow(env, surface)) == NULL) { 759 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 760 return BAD_VALUE; 761 } 762 status_t err = NO_ERROR; 763 if ((err = native_window_set_scaling_mode(anw.get(), static_cast<int>(mode))) != NO_ERROR) { 764 ALOGE("%s: Unable to set surface scaling mode, error %s (%d)", __FUNCTION__, 765 strerror(-err), err); 766 return err; 767 } 768 return NO_ERROR; 769 } 770 771 static jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) { 772 ALOGV("nativeGetJpegFooterSize"); 773 return static_cast<jint>(sizeof(struct camera3_jpeg_blob)); 774 } 775 776 } // extern "C" 777 778 static const JNINativeMethod gCameraDeviceMethods[] = { 779 { "nativeDetectSurfaceType", 780 "(Landroid/view/Surface;)I", 781 (void *)LegacyCameraDevice_nativeDetectSurfaceType }, 782 { "nativeDetectSurfaceDataspace", 783 "(Landroid/view/Surface;)I", 784 (void *)LegacyCameraDevice_nativeDetectSurfaceDataspace }, 785 { "nativeDetectSurfaceDimens", 786 "(Landroid/view/Surface;[I)I", 787 (void *)LegacyCameraDevice_nativeDetectSurfaceDimens }, 788 { "nativeConnectSurface", 789 "(Landroid/view/Surface;)I", 790 (void *)LegacyCameraDevice_nativeConnectSurface }, 791 { "nativeProduceFrame", 792 "(Landroid/view/Surface;[BIII)I", 793 (void *)LegacyCameraDevice_nativeProduceFrame }, 794 { "nativeSetSurfaceFormat", 795 "(Landroid/view/Surface;I)I", 796 (void *)LegacyCameraDevice_nativeSetSurfaceFormat }, 797 { "nativeSetSurfaceDimens", 798 "(Landroid/view/Surface;II)I", 799 (void *)LegacyCameraDevice_nativeSetSurfaceDimens }, 800 { "nativeGetSurfaceId", 801 "(Landroid/view/Surface;)J", 802 (void *)LegacyCameraDevice_nativeGetSurfaceId }, 803 { "nativeDetectTextureDimens", 804 "(Landroid/graphics/SurfaceTexture;[I)I", 805 (void *)LegacyCameraDevice_nativeDetectTextureDimens }, 806 { "nativeSetSurfaceOrientation", 807 "(Landroid/view/Surface;II)I", 808 (void *)LegacyCameraDevice_nativeSetSurfaceOrientation }, 809 { "nativeSetNextTimestamp", 810 "(Landroid/view/Surface;J)I", 811 (void *)LegacyCameraDevice_nativeSetNextTimestamp }, 812 { "nativeGetJpegFooterSize", 813 "()I", 814 (void *)LegacyCameraDevice_nativeGetJpegFooterSize }, 815 { "nativeDetectSurfaceUsageFlags", 816 "(Landroid/view/Surface;)I", 817 (void *)LegacyCameraDevice_nativeDetectSurfaceUsageFlags }, 818 { "nativeSetScalingMode", 819 "(Landroid/view/Surface;I)I", 820 (void *)LegacyCameraDevice_nativeSetScalingMode }, 821 { "nativeDisconnectSurface", 822 "(Landroid/view/Surface;)I", 823 (void *)LegacyCameraDevice_nativeDisconnectSurface }, 824 }; 825 826 // Get all the required offsets in java class and register native functions 827 int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env) 828 { 829 // Register native functions 830 return RegisterMethodsOrDie(env, 831 CAMERA_DEVICE_CLASS_NAME, 832 gCameraDeviceMethods, 833 NELEM(gCameraDeviceMethods)); 834 } 835