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