android_hardware_camera2_legacy_LegacyCameraDevice.cpp revision f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3
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 grallocBufWidth = buf->getWidth(); 197 uint32_t grallocBufHeight = buf->getHeight(); 198 uint32_t grallocBufStride = buf->getStride(); 199 if (grallocBufWidth != width || grallocBufHeight != height) { 200 ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32 201 ", expecting dimensions %zu x %zu", __FUNCTION__, grallocBufWidth, 202 grallocBufHeight, width, height); 203 return BAD_VALUE; 204 } 205 206 int32_t bufFmt = 0; 207 err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &bufFmt); 208 if (err != NO_ERROR) { 209 ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, 210 strerror(-err), err); 211 return err; 212 } 213 214 uint64_t tmpSize = (pixelFmt == HAL_PIXEL_FORMAT_BLOB) ? grallocBufWidth : 215 4 * grallocBufHeight * grallocBufWidth; 216 if (bufFmt != pixelFmt) { 217 if (bufFmt == HAL_PIXEL_FORMAT_RGBA_8888 && pixelFmt == HAL_PIXEL_FORMAT_BLOB) { 218 ALOGV("%s: Using BLOB to RGBA format override.", __FUNCTION__); 219 tmpSize = 4 * (grallocBufWidth + grallocBufStride * (grallocBufHeight - 1)); 220 } else { 221 ALOGW("%s: Format mismatch in produceFrame: expecting format %#" PRIx32 222 ", but received buffer with format %#" PRIx32, __FUNCTION__, pixelFmt, bufFmt); 223 } 224 } 225 226 if (tmpSize > SIZE_MAX) { 227 ALOGE("%s: Overflow calculating size, buffer with dimens %zu x %zu is absurdly large...", 228 __FUNCTION__, width, height); 229 return BAD_VALUE; 230 } 231 232 size_t totalSizeBytes = tmpSize; 233 234 switch(pixelFmt) { 235 case HAL_PIXEL_FORMAT_YCrCb_420_SP: { 236 if (bufferLength < totalSizeBytes) { 237 ALOGE("%s: PixelBuffer size %zu too small for given dimensions", 238 __FUNCTION__, bufferLength); 239 return BAD_VALUE; 240 } 241 uint8_t* img = NULL; 242 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); 243 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 244 if (err != NO_ERROR) return err; 245 246 uint8_t* yPlane = img; 247 uint8_t* uPlane = img + height * width; 248 uint8_t* vPlane = uPlane + 1; 249 size_t chromaStep = 2; 250 size_t yStride = width; 251 size_t chromaStride = width; 252 253 rgbToYuv420(pixelBuffer, width, height, yPlane, 254 uPlane, vPlane, chromaStep, yStride, chromaStride); 255 break; 256 } 257 case HAL_PIXEL_FORMAT_YV12: { 258 if (bufferLength < totalSizeBytes) { 259 ALOGE("%s: PixelBuffer size %zu too small for given dimensions", 260 __FUNCTION__, bufferLength); 261 return BAD_VALUE; 262 } 263 264 if ((width & 1) || (height & 1)) { 265 ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height); 266 return BAD_VALUE; 267 } 268 269 uint8_t* img = NULL; 270 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); 271 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 272 if (err != NO_ERROR) { 273 ALOGE("%s: Error %s (%d) while locking gralloc buffer for write.", __FUNCTION__, 274 strerror(-err), err); 275 return err; 276 } 277 278 uint32_t stride = buf->getStride(); 279 LOG_ALWAYS_FATAL_IF(stride % 16, "Stride is not 16 pixel aligned %d", stride); 280 281 uint32_t cStride = ALIGN(stride / 2, 16); 282 size_t chromaStep = 1; 283 284 uint8_t* yPlane = img; 285 uint8_t* crPlane = img + static_cast<uint32_t>(height) * stride; 286 uint8_t* cbPlane = crPlane + cStride * static_cast<uint32_t>(height) / 2; 287 288 rgbToYuv420(pixelBuffer, width, height, yPlane, 289 crPlane, cbPlane, chromaStep, stride, cStride); 290 break; 291 } 292 case HAL_PIXEL_FORMAT_YCbCr_420_888: { 293 // Software writes with YCbCr_420_888 format are unsupported 294 // by the gralloc module for now 295 if (bufferLength < totalSizeBytes) { 296 ALOGE("%s: PixelBuffer size %zu too small for given dimensions", 297 __FUNCTION__, bufferLength); 298 return BAD_VALUE; 299 } 300 android_ycbcr ycbcr = android_ycbcr(); 301 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); 302 303 err = buf->lockYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr); 304 if (err != NO_ERROR) { 305 ALOGE("%s: Failed to lock ycbcr buffer, error %s (%d).", __FUNCTION__, 306 strerror(-err), err); 307 return err; 308 } 309 rgbToYuv420(pixelBuffer, width, height, &ycbcr); 310 break; 311 } 312 case HAL_PIXEL_FORMAT_BLOB: { 313 int8_t* img = NULL; 314 struct camera3_jpeg_blob footer = { 315 jpeg_blob_id: CAMERA3_JPEG_BLOB_ID, 316 jpeg_size: (uint32_t)bufferLength 317 }; 318 319 size_t totalJpegSize = bufferLength + sizeof(footer); 320 totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble 321 322 if (totalJpegSize > totalSizeBytes) { 323 ALOGE("%s: Pixel buffer needs size %zu, cannot fit in gralloc buffer of size %zu", 324 __FUNCTION__, totalJpegSize, totalSizeBytes); 325 return BAD_VALUE; 326 } 327 328 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 329 if (err != NO_ERROR) { 330 ALOGE("%s: Failed to lock buffer, error %s (%d).", __FUNCTION__, strerror(-err), 331 err); 332 return err; 333 } 334 335 memcpy(img, pixelBuffer, bufferLength); 336 memcpy(img + totalSizeBytes - sizeof(footer), &footer, sizeof(footer)); 337 break; 338 } 339 default: { 340 ALOGE("%s: Invalid pixel format in produceFrame: %x", __FUNCTION__, pixelFmt); 341 return BAD_VALUE; 342 } 343 } 344 345 ALOGV("%s: Unlock buffer from %p", __FUNCTION__, anw.get()); 346 err = buf->unlock(); 347 if (err != NO_ERROR) { 348 ALOGE("%s: Failed to unlock buffer, error %s (%d).", __FUNCTION__, strerror(-err), err); 349 return err; 350 } 351 352 ALOGV("%s: Queue buffer to %p", __FUNCTION__, anw.get()); 353 err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), /*fenceFd*/-1); 354 if (err != NO_ERROR) { 355 ALOGE("%s: Failed to queue buffer, error %s (%d).", __FUNCTION__, strerror(-err), err); 356 return err; 357 } 358 return NO_ERROR; 359} 360 361static sp<ANativeWindow> getNativeWindow(JNIEnv* env, jobject surface) { 362 sp<ANativeWindow> anw; 363 if (surface) { 364 anw = android_view_Surface_getNativeWindow(env, surface); 365 if (env->ExceptionCheck()) { 366 return NULL; 367 } 368 } else { 369 jniThrowNullPointerException(env, "surface"); 370 return NULL; 371 } 372 if (anw == NULL) { 373 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 374 "Surface had no valid native window."); 375 return NULL; 376 } 377 return anw; 378} 379 380static sp<ANativeWindow> getNativeWindowFromTexture(JNIEnv* env, jobject surfaceTexture) { 381 sp<ANativeWindow> anw; 382 if (surfaceTexture) { 383 anw = android_SurfaceTexture_getNativeWindow(env, surfaceTexture); 384 if (env->ExceptionCheck()) { 385 return NULL; 386 } 387 } else { 388 jniThrowNullPointerException(env, "surfaceTexture"); 389 return NULL; 390 } 391 if (anw == NULL) { 392 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 393 "SurfaceTexture had no valid native window."); 394 return NULL; 395 } 396 return anw; 397} 398 399static sp<Surface> getSurface(JNIEnv* env, jobject surface) { 400 sp<Surface> s; 401 if (surface) { 402 s = android_view_Surface_getSurface(env, surface); 403 if (env->ExceptionCheck()) { 404 return NULL; 405 } 406 } else { 407 jniThrowNullPointerException(env, "surface"); 408 return NULL; 409 } 410 if (s == NULL) { 411 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 412 "Surface had no valid native Surface."); 413 return NULL; 414 } 415 return s; 416} 417 418extern "C" { 419 420static jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) { 421 ALOGV("nativeDetectSurfaceType"); 422 sp<ANativeWindow> anw; 423 if ((anw = getNativeWindow(env, surface)) == NULL) { 424 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 425 return BAD_VALUE; 426 } 427 int32_t fmt = 0; 428 status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt); 429 if(err != NO_ERROR) { 430 ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err), 431 err); 432 return err; 433 } 434 return fmt; 435} 436 437static jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz, 438 jobject surface, jintArray dimens) { 439 ALOGV("nativeGetSurfaceDimens"); 440 441 if (dimens == NULL) { 442 ALOGE("%s: Null dimens argument passed to nativeDetectSurfaceDimens", __FUNCTION__); 443 return BAD_VALUE; 444 } 445 446 if (env->GetArrayLength(dimens) < 2) { 447 ALOGE("%s: Invalid length of dimens argument in nativeDetectSurfaceDimens", __FUNCTION__); 448 return BAD_VALUE; 449 } 450 451 sp<ANativeWindow> anw; 452 if ((anw = getNativeWindow(env, surface)) == NULL) { 453 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 454 return BAD_VALUE; 455 } 456 int32_t dimenBuf[2]; 457 status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf); 458 if(err != NO_ERROR) { 459 ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err), 460 err); 461 return err; 462 } 463 err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1); 464 if(err != NO_ERROR) { 465 ALOGE("%s: Error while querying surface height %s (%d).", __FUNCTION__, strerror(-err), 466 err); 467 return err; 468 } 469 env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf); 470 return NO_ERROR; 471} 472 473static jint LegacyCameraDevice_nativeDetectSurfaceUsageFlags(JNIEnv* env, jobject thiz, 474 jobject surface) { 475 ALOGV("nativeDetectSurfaceUsageFlags"); 476 477 sp<ANativeWindow> anw; 478 if ((anw = getNativeWindow(env, surface)) == NULL) { 479 jniThrowException(env, "Ljava/lang/UnsupportedOperationException;", 480 "Could not retrieve native window from surface."); 481 return BAD_VALUE; 482 } 483 int32_t usage = 0; 484 status_t err = anw->query(anw.get(), NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage); 485 if(err != NO_ERROR) { 486 jniThrowException(env, "Ljava/lang/UnsupportedOperationException;", 487 "Error while querying surface usage bits"); 488 return err; 489 } 490 return usage; 491} 492 493static jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz, 494 jobject surfaceTexture, jintArray dimens) { 495 ALOGV("nativeDetectTextureDimens"); 496 sp<ANativeWindow> anw; 497 if ((anw = getNativeWindowFromTexture(env, surfaceTexture)) == NULL) { 498 ALOGE("%s: Could not retrieve native window from SurfaceTexture.", __FUNCTION__); 499 return BAD_VALUE; 500 } 501 502 int32_t dimenBuf[2]; 503 status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf); 504 if(err != NO_ERROR) { 505 ALOGE("%s: Error while querying SurfaceTexture width %s (%d)", __FUNCTION__, 506 strerror(-err), err); 507 return err; 508 } 509 510 err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1); 511 if(err != NO_ERROR) { 512 ALOGE("%s: Error while querying SurfaceTexture height %s (%d)", __FUNCTION__, 513 strerror(-err), err); 514 return err; 515 } 516 517 env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf); 518 if (env->ExceptionCheck()) { 519 return BAD_VALUE; 520 } 521 return NO_ERROR; 522} 523 524static jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface, 525 jint width, jint height, jint pixelFormat) { 526 ALOGV("nativeConfigureSurface"); 527 sp<ANativeWindow> anw; 528 if ((anw = getNativeWindow(env, surface)) == NULL) { 529 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 530 return BAD_VALUE; 531 } 532 status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK); 533 if (err != NO_ERROR) { 534 ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err); 535 return err; 536 } 537 return NO_ERROR; 538} 539 540static jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface, 541 jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) { 542 ALOGV("nativeProduceFrame"); 543 sp<ANativeWindow> anw; 544 545 if ((anw = getNativeWindow(env, surface)) == NULL) { 546 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 547 return BAD_VALUE; 548 } 549 550 if (pixelBuffer == NULL) { 551 jniThrowNullPointerException(env, "pixelBuffer"); 552 return DONT_CARE; 553 } 554 555 int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer)); 556 jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL); 557 558 if (pixels == NULL) { 559 jniThrowNullPointerException(env, "pixels"); 560 return DONT_CARE; 561 } 562 563 status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height, 564 pixelFormat, bufSize); 565 env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT); 566 567 if (err != NO_ERROR) { 568 ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err); 569 return err; 570 } 571 return NO_ERROR; 572} 573 574static jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface, 575 jint pixelFormat) { 576 ALOGV("nativeSetSurfaceType"); 577 sp<ANativeWindow> anw; 578 if ((anw = getNativeWindow(env, surface)) == NULL) { 579 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 580 return BAD_VALUE; 581 } 582 status_t err = native_window_set_buffers_format(anw.get(), pixelFormat); 583 if (err != NO_ERROR) { 584 ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err); 585 return err; 586 } 587 return NO_ERROR; 588} 589 590static jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface, 591 jint width, jint height) { 592 ALOGV("nativeSetSurfaceDimens"); 593 sp<ANativeWindow> anw; 594 if ((anw = getNativeWindow(env, surface)) == NULL) { 595 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 596 return BAD_VALUE; 597 } 598 status_t err = native_window_set_buffers_dimensions(anw.get(), width, height); 599 if (err != NO_ERROR) { 600 ALOGE("%s: Error while setting surface dimens %s (%d).", __FUNCTION__, strerror(-err), err); 601 return err; 602 } 603 604 // WAR - Set user dimensions also to avoid incorrect scaling after TextureView orientation 605 // change. 606 err = native_window_set_buffers_user_dimensions(anw.get(), width, height); 607 if (err != NO_ERROR) { 608 ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err), 609 err); 610 return err; 611 } 612 return NO_ERROR; 613} 614 615static jlong LegacyCameraDevice_nativeGetSurfaceId(JNIEnv* env, jobject thiz, jobject surface) { 616 ALOGV("nativeGetSurfaceId"); 617 sp<Surface> s; 618 if ((s = getSurface(env, surface)) == NULL) { 619 ALOGE("%s: Could not retrieve native Surface from surface.", __FUNCTION__); 620 return 0; 621 } 622 sp<IGraphicBufferProducer> gbp = s->getIGraphicBufferProducer(); 623 if (gbp == NULL) { 624 ALOGE("%s: Could not retrieve IGraphicBufferProducer from surface.", __FUNCTION__); 625 return 0; 626 } 627 sp<IBinder> b = gbp->asBinder(); 628 if (b == NULL) { 629 ALOGE("%s: Could not retrieve IBinder from surface.", __FUNCTION__); 630 return 0; 631 } 632 /* 633 * FIXME: Use better unique ID for surfaces than native IBinder pointer. Fix also in the camera 634 * service (CameraDeviceClient.h). 635 */ 636 return reinterpret_cast<jlong>(b.get()); 637} 638 639static jint LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv* env, jobject thiz, 640 jobject surface, jint facing, jint orientation) { 641 ALOGV("nativeSetSurfaceOrientation"); 642 sp<ANativeWindow> anw; 643 if ((anw = getNativeWindow(env, surface)) == NULL) { 644 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 645 return BAD_VALUE; 646 } 647 648 status_t err = NO_ERROR; 649 CameraMetadata staticMetadata; 650 651 int32_t orientVal = static_cast<int32_t>(orientation); 652 uint8_t facingVal = static_cast<uint8_t>(facing); 653 staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1); 654 staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1); 655 656 int32_t transform = 0; 657 658 if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) { 659 ALOGE("%s: Invalid rotation transform %s (%d)", __FUNCTION__, strerror(-err), 660 err); 661 return err; 662 } 663 664 ALOGV("%s: Setting buffer sticky transform to %d", __FUNCTION__, transform); 665 666 if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) { 667 ALOGE("%s: Unable to configure surface transform, error %s (%d)", __FUNCTION__, 668 strerror(-err), err); 669 return err; 670 } 671 672 return NO_ERROR; 673} 674 675static jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz, jobject surface, 676 jlong timestamp) { 677 ALOGV("nativeSetNextTimestamp"); 678 sp<ANativeWindow> anw; 679 if ((anw = getNativeWindow(env, surface)) == NULL) { 680 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 681 return BAD_VALUE; 682 } 683 684 status_t err = NO_ERROR; 685 686 if ((err = native_window_set_buffers_timestamp(anw.get(), static_cast<int64_t>(timestamp))) != 687 NO_ERROR) { 688 ALOGE("%s: Unable to set surface timestamp, error %s (%d)", __FUNCTION__, strerror(-err), 689 err); 690 return err; 691 } 692 return NO_ERROR; 693} 694 695static jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) { 696 ALOGV("nativeGetJpegFooterSize"); 697 return static_cast<jint>(sizeof(struct camera3_jpeg_blob)); 698} 699 700} // extern "C" 701 702static JNINativeMethod gCameraDeviceMethods[] = { 703 { "nativeDetectSurfaceType", 704 "(Landroid/view/Surface;)I", 705 (void *)LegacyCameraDevice_nativeDetectSurfaceType }, 706 { "nativeDetectSurfaceDimens", 707 "(Landroid/view/Surface;[I)I", 708 (void *)LegacyCameraDevice_nativeDetectSurfaceDimens }, 709 { "nativeConfigureSurface", 710 "(Landroid/view/Surface;III)I", 711 (void *)LegacyCameraDevice_nativeConfigureSurface }, 712 { "nativeProduceFrame", 713 "(Landroid/view/Surface;[BIII)I", 714 (void *)LegacyCameraDevice_nativeProduceFrame }, 715 { "nativeSetSurfaceFormat", 716 "(Landroid/view/Surface;I)I", 717 (void *)LegacyCameraDevice_nativeSetSurfaceFormat }, 718 { "nativeSetSurfaceDimens", 719 "(Landroid/view/Surface;II)I", 720 (void *)LegacyCameraDevice_nativeSetSurfaceDimens }, 721 { "nativeGetSurfaceId", 722 "(Landroid/view/Surface;)J", 723 (void *)LegacyCameraDevice_nativeGetSurfaceId }, 724 { "nativeDetectTextureDimens", 725 "(Landroid/graphics/SurfaceTexture;[I)I", 726 (void *)LegacyCameraDevice_nativeDetectTextureDimens }, 727 { "nativeSetSurfaceOrientation", 728 "(Landroid/view/Surface;II)I", 729 (void *)LegacyCameraDevice_nativeSetSurfaceOrientation }, 730 { "nativeSetNextTimestamp", 731 "(Landroid/view/Surface;J)I", 732 (void *)LegacyCameraDevice_nativeSetNextTimestamp }, 733 { "nativeGetJpegFooterSize", 734 "()I", 735 (void *)LegacyCameraDevice_nativeGetJpegFooterSize }, 736 { "nativeDetectSurfaceUsageFlags", 737 "(Landroid/view/Surface;)I", 738 (void *)LegacyCameraDevice_nativeDetectSurfaceUsageFlags }, 739}; 740 741// Get all the required offsets in java class and register native functions 742int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env) 743{ 744 // Register native functions 745 return AndroidRuntime::registerNativeMethods(env, 746 CAMERA_DEVICE_CLASS_NAME, 747 gCameraDeviceMethods, 748 NELEM(gCameraDeviceMethods)); 749} 750 751