android_hardware_camera2_legacy_LegacyCameraDevice.cpp revision ef14da32804b06bac872c9e0e14ce0e52120a0bd
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/* 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * Copyright (C) 2014 The Android Open Source Project 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * Licensed under the Apache License, Version 2.0 (the "License"); 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * you may not use this file except in compliance with the License. 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * You may obtain a copy of the License at 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * http://www.apache.org/licenses/LICENSE-2.0 95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * 105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * Unless required by applicable law or agreed to in writing, software 115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * distributed under the License is distributed on an "AS IS" BASIS, 125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * See the License for the specific language governing permissions and 1487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * limitations under the License. 1587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines */ 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#define LOG_TAG "Legacy-CameraDevice-JNI" 18affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// #define LOG_NDEBUG 0 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <utils/Log.h> 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <utils/Errors.h> 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <utils/Trace.h> 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "jni.h" 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "JNIHelp.h" 25affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include "android_runtime/AndroidRuntime.h" 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "android_runtime/android_view_Surface.h" 275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <ui/GraphicBuffer.h> 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <system/window.h> 305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <hardware/camera3.h> 315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace android; 335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// fully-qualified class name 355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#define CAMERA_DEVICE_CLASS_NAME "android/hardware/camera2/legacy/LegacyCameraDevice" 365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#define CAMERA_DEVICE_BUFFER_SLACK 3 375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#define DONT_CARE 0 385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) ) 425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/** 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * Convert from RGB 888 to Y'CbCr using the conversion specified in ITU-R BT.601 for 455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * digital RGB with K_b = 0.114, and K_r = 0.299. 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao */ 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic void rgbToYuv420(uint8_t* rgbBuf, int32_t width, int32_t height, uint8_t* yPlane, 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint8_t* uPlane, uint8_t* vPlane, size_t chromaStep, size_t yStride, size_t chromaStride) { 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint8_t R, G, B; 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t index = 0; 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t cStrideDiff = chromaStride - width; 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for (int32_t j = 0; j < height; j++) { 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for (int32_t i = 0; i < width; i++) { 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao R = rgbBuf[index++]; 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao G = rgbBuf[index++]; 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao B = rgbBuf[index++]; 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *(yPlane + i) = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16; 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (j % 2 == 0 && i % 2 == 0){ 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *uPlane = (( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128; 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *vPlane = (( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128; 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uPlane += chromaStep; 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao vPlane += chromaStep; 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Skip alpha 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao index++; 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao yPlane += yStride; 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (j % 2 == 0) { 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uPlane += cStrideDiff; 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao vPlane += cStrideDiff; 745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic void rgbToYuv420(uint8_t* rgbBuf, int32_t width, int32_t height, android_ycbcr* ycbcr) { 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t cStep = ycbcr->chroma_step; 80f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines size_t cStride = ycbcr->cstride; 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t yStride = ycbcr->ystride; 82f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rgbToYuv420(rgbBuf, width, height, reinterpret_cast<uint8_t*>(ycbcr->y), 83f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines reinterpret_cast<uint8_t*>(ycbcr->cb), reinterpret_cast<uint8_t*>(ycbcr->cr), 84f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines cStep, yStride, cStride); 85f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 86f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 87f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesstatic status_t configureSurface(const sp<ANativeWindow>& anw, 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t width, 89f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines int32_t height, 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t pixelFmt, 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t maxBufferSlack) { 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao status_t err = NO_ERROR; 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao err = native_window_set_buffers_dimensions(anw.get(), width, height); 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (err != NO_ERROR) { 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ALOGE("%s: Failed to set native window buffer dimensions, error %s (%d).", __FUNCTION__, 96f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines strerror(-err), err); 97affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return err; 98affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 99affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 100f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines err = native_window_set_buffers_format(anw.get(), pixelFmt); 101f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (err != NO_ERROR) { 102affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ALOGE("%s: Failed to set native window buffer format, error %s (%d).", __FUNCTION__, 103f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines strerror(-err), err); 104f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return err; 105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao err = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN); 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (err != NO_ERROR) { 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__, 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao strerror(-err), err); 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return err; 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 114 int minUndequeuedBuffers; 115 err = anw.get()->query(anw.get(), 116 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 117 &minUndequeuedBuffers); 118 if (err != NO_ERROR) { 119 ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).", 120 __FUNCTION__, strerror(-err), err); 121 return err; 122 } 123 124 ALOGV("%s: Setting buffer count to %d, size to (%dx%d), fmt (0x%x)", __FUNCTION__, 125 maxBufferSlack + 1 + minUndequeuedBuffers, 126 width, height, pixelFmt); 127 err = native_window_set_buffer_count(anw.get(), maxBufferSlack + 1 + minUndequeuedBuffers); 128 if (err != NO_ERROR) { 129 ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__, 130 strerror(-err), err); 131 return err; 132 } 133 return NO_ERROR; 134} 135 136/** 137 * Produce a frame in the given surface. 138 * 139 * Args: 140 * anw - a surface to produce a frame in. 141 * pixelBuffer - image buffer to generate a frame from. 142 * width - width of the pixelBuffer in pixels. 143 * height - height of the pixelBuffer in pixels. 144 * pixelFmt - format of the pixelBuffer, one of: 145 * HAL_PIXEL_FORMAT_YCrCb_420_SP, 146 * HAL_PIXEL_FORMAT_YCbCr_420_888, 147 * HAL_PIXEL_FORMAT_BLOB 148 * bufSize - the size of the pixelBuffer in bytes. 149 */ 150static status_t produceFrame(const sp<ANativeWindow>& anw, 151 uint8_t* pixelBuffer, 152 int32_t width, // Width of the pixelBuffer 153 int32_t height, // Height of the pixelBuffer 154 int32_t pixelFmt, // Format of the pixelBuffer 155 int32_t bufSize) { 156 ATRACE_CALL(); 157 status_t err = NO_ERROR; 158 ANativeWindowBuffer* anb; 159 ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)", 160 __FUNCTION__, anw.get(), width, height, pixelFmt, bufSize); 161 162 if (anw == 0) { 163 ALOGE("%s: anw must not be NULL", __FUNCTION__); 164 return BAD_VALUE; 165 } else if (pixelBuffer == NULL) { 166 ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__); 167 return BAD_VALUE; 168 } else if (width < 0) { 169 ALOGE("%s: width must be non-negative", __FUNCTION__); 170 return BAD_VALUE; 171 } else if (height < 0) { 172 ALOGE("%s: height must be non-negative", __FUNCTION__); 173 return BAD_VALUE; 174 } else if (bufSize < 0) { 175 ALOGE("%s: bufSize must be non-negative", __FUNCTION__); 176 return BAD_VALUE; 177 } 178 179 if (width < 0 || height < 0 || bufSize < 0) { 180 ALOGE("%s: Illegal argument, negative dimension passed to produceFrame", __FUNCTION__); 181 return BAD_VALUE; 182 } 183 184 // TODO: Switch to using Surface::lock and Surface::unlockAndPost 185 err = native_window_dequeue_buffer_and_wait(anw.get(), &anb); 186 if (err != NO_ERROR) return err; 187 188 // TODO: check anb is large enough to store the results 189 190 sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false)); 191 192 switch(pixelFmt) { 193 case HAL_PIXEL_FORMAT_YCrCb_420_SP: { 194 if (bufSize < width * height * 4) { 195 ALOGE("%s: PixelBuffer size %lld to small for given dimensions", __FUNCTION__, 196 bufSize); 197 return BAD_VALUE; 198 } 199 uint8_t* img = NULL; 200 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); 201 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 202 if (err != NO_ERROR) return err; 203 204 uint8_t* yPlane = img; 205 uint8_t* uPlane = img + height * width; 206 uint8_t* vPlane = uPlane + 1; 207 size_t chromaStep = 2; 208 size_t yStride = width; 209 size_t chromaStride = width; 210 211 rgbToYuv420(pixelBuffer, width, height, yPlane, 212 uPlane, vPlane, chromaStep, yStride, chromaStride); 213 break; 214 } 215 case HAL_PIXEL_FORMAT_YV12: { 216 if (bufSize < width * height * 4) { 217 ALOGE("%s: PixelBuffer size %lld to small for given dimensions", __FUNCTION__, 218 bufSize); 219 return BAD_VALUE; 220 } 221 222 if ((width & 1) || (height & 1)) { 223 ALOGE("%s: Dimens %dx%d are not divisible by 2.", __FUNCTION__, width, height); 224 return BAD_VALUE; 225 } 226 227 uint8_t* img = NULL; 228 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); 229 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 230 if (err != NO_ERROR) { 231 ALOGE("%s: Error %s (%d) while locking gralloc buffer for write.", __FUNCTION__, 232 strerror(-err), err); 233 return err; 234 } 235 236 uint32_t stride = buf->getStride(); 237 LOG_ALWAYS_FATAL_IF(stride % 16, "Stride is not 16 pixel aligned %d", stride); 238 239 uint32_t cStride = ALIGN(stride / 2, 16); 240 size_t chromaStep = 1; 241 242 uint8_t* yPlane = img; 243 uint8_t* crPlane = img + static_cast<uint32_t>(height) * stride; 244 uint8_t* cbPlane = crPlane + cStride * static_cast<uint32_t>(height) / 2; 245 246 rgbToYuv420(pixelBuffer, width, height, yPlane, 247 crPlane, cbPlane, chromaStep, stride, cStride); 248 break; 249 } 250 case HAL_PIXEL_FORMAT_YCbCr_420_888: { 251 // Software writes with YCbCr_420_888 format are unsupported 252 // by the gralloc module for now 253 if (bufSize < width * height * 4) { 254 ALOGE("%s: PixelBuffer size %lld to small for given dimensions", __FUNCTION__, 255 bufSize); 256 return BAD_VALUE; 257 } 258 android_ycbcr ycbcr = android_ycbcr(); 259 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); 260 261 err = buf->lockYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr); 262 if (err != NO_ERROR) { 263 ALOGE("%s: Failed to lock ycbcr buffer, error %s (%d).", __FUNCTION__, 264 strerror(-err), err); 265 return err; 266 } 267 rgbToYuv420(pixelBuffer, width, height, &ycbcr); 268 break; 269 } 270 case HAL_PIXEL_FORMAT_BLOB: { 271 if (bufSize != width || height != 1) { 272 ALOGE("%s: Incorrect pixelBuffer size: %lld", __FUNCTION__, bufSize); 273 return BAD_VALUE; 274 } 275 int8_t* img = NULL; 276 277 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get()); 278 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 279 if (err != NO_ERROR) { 280 ALOGE("%s: Failed to lock buffer, error %s (%d).", __FUNCTION__, strerror(-err), 281 err); 282 return err; 283 } 284 struct camera3_jpeg_blob footer = { 285 jpeg_blob_id: CAMERA3_JPEG_BLOB_ID, 286 jpeg_size: (uint32_t)width 287 }; 288 memcpy(img, pixelBuffer, width); 289 memcpy(img + anb->width - sizeof(footer), &footer, sizeof(footer)); 290 break; 291 } 292 default: { 293 ALOGE("%s: Invalid pixel format in produceFrame: %x", __FUNCTION__, pixelFmt); 294 return BAD_VALUE; 295 } 296 } 297 298 ALOGV("%s: Unlock buffer from %p", __FUNCTION__, anw.get()); 299 err = buf->unlock(); 300 if (err != NO_ERROR) { 301 ALOGE("%s: Failed to unlock buffer, error %s (%d).", __FUNCTION__, strerror(-err), err); 302 return err; 303 } 304 305 ALOGV("%s: Queue buffer to %p", __FUNCTION__, anw.get()); 306 err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), /*fenceFd*/-1); 307 if (err != NO_ERROR) { 308 ALOGE("%s: Failed to queue buffer, error %s (%d).", __FUNCTION__, strerror(-err), err); 309 return err; 310 } 311 return NO_ERROR; 312} 313 314static sp<ANativeWindow> getNativeWindow(JNIEnv* env, jobject surface) { 315 sp<ANativeWindow> anw; 316 if (surface) { 317 anw = android_view_Surface_getNativeWindow(env, surface); 318 if (env->ExceptionCheck()) { 319 return anw; 320 } 321 } else { 322 jniThrowNullPointerException(env, "surface"); 323 return anw; 324 } 325 if (anw == NULL) { 326 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 327 "Surface had no valid native window."); 328 return anw; 329 } 330 return anw; 331} 332 333extern "C" { 334 335static jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) { 336 ALOGV("nativeDetectSurfaceType"); 337 sp<ANativeWindow> anw; 338 if ((anw = getNativeWindow(env, surface)) == NULL) { 339 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 340 return BAD_VALUE; 341 } 342 int32_t fmt = 0; 343 status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt); 344 if(err != NO_ERROR) { 345 ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err), 346 err); 347 return err; 348 } 349 return fmt; 350} 351 352static jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz, 353 jobject surface, jintArray dimens) { 354 ALOGV("nativeGetSurfaceDimens"); 355 sp<ANativeWindow> anw; 356 if ((anw = getNativeWindow(env, surface)) == NULL) { 357 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 358 return BAD_VALUE; 359 } 360 int32_t dimenBuf[2]; 361 status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf); 362 if(err != NO_ERROR) { 363 ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err), 364 err); 365 return err; 366 } 367 err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1); 368 if(err != NO_ERROR) { 369 ALOGE("%s: Error while querying surface height %s (%d).", __FUNCTION__, strerror(-err), 370 err); 371 return err; 372 } 373 env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf); 374 return NO_ERROR; 375} 376 377static jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface, 378 jint width, jint height, jint pixelFormat) { 379 ALOGV("nativeConfigureSurface"); 380 sp<ANativeWindow> anw; 381 if ((anw = getNativeWindow(env, surface)) == NULL) { 382 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 383 return BAD_VALUE; 384 } 385 status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK); 386 if (err != NO_ERROR) { 387 ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err); 388 return err; 389 } 390 return NO_ERROR; 391} 392 393static jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface, 394 jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) { 395 ALOGV("nativeProduceFrame"); 396 sp<ANativeWindow> anw; 397 398 if ((anw = getNativeWindow(env, surface)) == NULL) { 399 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 400 return BAD_VALUE; 401 } 402 403 if (pixelBuffer == NULL) { 404 jniThrowNullPointerException(env, "pixelBuffer"); 405 return DONT_CARE; 406 } 407 408 int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer)); 409 jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL); 410 411 if (pixels == NULL) { 412 jniThrowNullPointerException(env, "pixels"); 413 return DONT_CARE; 414 } 415 416 status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height, 417 pixelFormat, bufSize); 418 env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT); 419 420 if (err != NO_ERROR) { 421 ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err); 422 return err; 423 } 424 return NO_ERROR; 425} 426 427static jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface, 428 jint pixelFormat) { 429 ALOGV("nativeSetSurfaceType"); 430 sp<ANativeWindow> anw; 431 if ((anw = getNativeWindow(env, surface)) == NULL) { 432 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 433 return BAD_VALUE; 434 } 435 status_t err = native_window_set_buffers_format(anw.get(), pixelFormat); 436 if (err != NO_ERROR) { 437 ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err); 438 return err; 439 } 440 return NO_ERROR; 441} 442 443static jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface, 444 jint width, jint height) { 445 ALOGV("nativeSetSurfaceDimens"); 446 sp<ANativeWindow> anw; 447 if ((anw = getNativeWindow(env, surface)) == NULL) { 448 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); 449 return BAD_VALUE; 450 } 451 status_t err = native_window_set_buffers_dimensions(anw.get(), width, height); 452 if (err != NO_ERROR) { 453 ALOGE("%s: Error while setting surface dimens %s (%d).", __FUNCTION__, strerror(-err), err); 454 return err; 455 } 456 return NO_ERROR; 457} 458 459} // extern "C" 460 461static JNINativeMethod gCameraDeviceMethods[] = { 462 { "nativeDetectSurfaceType", 463 "(Landroid/view/Surface;)I", 464 (void *)LegacyCameraDevice_nativeDetectSurfaceType }, 465 { "nativeDetectSurfaceDimens", 466 "(Landroid/view/Surface;[I)I", 467 (void *)LegacyCameraDevice_nativeDetectSurfaceDimens }, 468 { "nativeConfigureSurface", 469 "(Landroid/view/Surface;III)I", 470 (void *)LegacyCameraDevice_nativeConfigureSurface }, 471 { "nativeProduceFrame", 472 "(Landroid/view/Surface;[BIII)I", 473 (void *)LegacyCameraDevice_nativeProduceFrame }, 474 { "nativeSetSurfaceFormat", 475 "(Landroid/view/Surface;I)I", 476 (void *)LegacyCameraDevice_nativeSetSurfaceFormat }, 477 { "nativeSetSurfaceDimens", 478 "(Landroid/view/Surface;II)I", 479 (void *)LegacyCameraDevice_nativeSetSurfaceDimens }, 480}; 481 482// Get all the required offsets in java class and register native functions 483int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env) 484{ 485 // Register native functions 486 return AndroidRuntime::registerNativeMethods(env, 487 CAMERA_DEVICE_CLASS_NAME, 488 gCameraDeviceMethods, 489 NELEM(gCameraDeviceMethods)); 490} 491 492