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