blob: 7497d8bdb4755dd5dfc83a3b42b525c19dec35e6 [file] [log] [blame]
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001/*
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"
Igor Murashkin5096def2014-06-24 10:49:11 -070018// #define LOG_NDEBUG 0
Ruben Brunkfeb50af2014-05-09 19:58:49 -070019#include <utils/Log.h>
20#include <utils/Errors.h>
21#include <utils/Trace.h>
Ruben Brunk28c49c92014-06-16 18:43:59 -070022#include <camera/CameraUtils.h>
Ruben Brunkfeb50af2014-05-09 19:58:49 -070023
24#include "jni.h"
25#include "JNIHelp.h"
Andreas Gampeed6b9df2014-11-20 22:02:20 -080026#include "core_jni_helpers.h"
Ruben Brunkfeb50af2014-05-09 19:58:49 -070027#include "android_runtime/android_view_Surface.h"
Ruben Brunk28c49c92014-06-16 18:43:59 -070028#include "android_runtime/android_graphics_SurfaceTexture.h"
Ruben Brunkfeb50af2014-05-09 19:58:49 -070029
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -070030#include <gui/Surface.h>
31#include <gui/IGraphicBufferProducer.h>
Ruben Brunkfeb50af2014-05-09 19:58:49 -070032#include <ui/GraphicBuffer.h>
33#include <system/window.h>
Igor Murashkin5096def2014-06-24 10:49:11 -070034#include <hardware/camera3.h>
Ruben Brunk28c49c92014-06-16 18:43:59 -070035#include <system/camera_metadata.h>
Ruben Brunkfeb50af2014-05-09 19:58:49 -070036
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -070037#include <stdint.h>
38#include <inttypes.h>
39
Ruben Brunkfeb50af2014-05-09 19:58:49 -070040using 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
Ruben Brunkef14da32014-06-24 16:06:54 -070045#define DONT_CARE 0
Ruben Brunkfeb50af2014-05-09 19:58:49 -070046
47#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
48
Ruben Brunk91b9aab2014-06-20 00:24:56 -070049#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
50
Ruben Brunkfeb50af2014-05-09 19:58:49 -070051/**
Ruben Brunk433e7152014-12-10 19:12:41 -080052 * Convert from RGB 888 to Y'CbCr using the conversion specified in JFIF v1.02
Ruben Brunkfeb50af2014-05-09 19:58:49 -070053 */
Ruben Brunk31798f32014-09-25 19:56:54 -070054static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane,
Ruben Brunkfeb50af2014-05-09 19:58:49 -070055 uint8_t* uPlane, uint8_t* vPlane, size_t chromaStep, size_t yStride, size_t chromaStride) {
56 uint8_t R, G, B;
57 size_t index = 0;
Ruben Brunk31798f32014-09-25 19:56:54 -070058 for (size_t j = 0; j < height; j++) {
Ruben Brunk433e7152014-12-10 19:12:41 -080059 uint8_t* u = uPlane;
60 uint8_t* v = vPlane;
61 uint8_t* y = yPlane;
62 bool jEven = (j & 1) == 0;
Ruben Brunk31798f32014-09-25 19:56:54 -070063 for (size_t i = 0; i < width; i++) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -070064 R = rgbBuf[index++];
65 G = rgbBuf[index++];
66 B = rgbBuf[index++];
Ruben Brunk433e7152014-12-10 19:12:41 -080067 *y++ = (77 * R + 150 * G + 29 * B) >> 8;
68 if (jEven && (i & 1) == 0) {
69 *v = (( -43 * R - 85 * G + 128 * B) >> 8) + 128;
70 *u = (( 128 * R - 107 * G - 21 * B) >> 8) + 128;
71 u += chromaStep;
72 v += chromaStep;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070073 }
74 // Skip alpha
75 index++;
76 }
77 yPlane += yStride;
Ruben Brunk433e7152014-12-10 19:12:41 -080078 if (jEven) {
79 uPlane += chromaStride;
80 vPlane += chromaStride;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070081 }
82 }
83}
84
Ruben Brunk31798f32014-09-25 19:56:54 -070085static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, android_ycbcr* ycbcr) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -070086 size_t cStep = ycbcr->chroma_step;
87 size_t cStride = ycbcr->cstride;
88 size_t yStride = ycbcr->ystride;
Ruben Brunk433e7152014-12-10 19:12:41 -080089 ALOGV("%s: yStride is: %zu, cStride is: %zu, cStep is: %zu", __FUNCTION__, yStride, cStride,
90 cStep);
Ruben Brunkfeb50af2014-05-09 19:58:49 -070091 rgbToYuv420(rgbBuf, width, height, reinterpret_cast<uint8_t*>(ycbcr->y),
Ruben Brunk433e7152014-12-10 19:12:41 -080092 reinterpret_cast<uint8_t*>(ycbcr->cr), reinterpret_cast<uint8_t*>(ycbcr->cb),
Ruben Brunkfeb50af2014-05-09 19:58:49 -070093 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
Igor Murashkin5096def2014-06-24 10:49:11 -0700133 ALOGV("%s: Setting buffer count to %d, size to (%dx%d), fmt (0x%x)", __FUNCTION__,
134 maxBufferSlack + 1 + minUndequeuedBuffers,
135 width, height, pixelFmt);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700136 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,
Ruben Brunk31798f32014-09-25 19:56:54 -0700161 int32_t bufWidth, // Width of the pixelBuffer
162 int32_t bufHeight, // Height of the pixelBuffer
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700163 int32_t pixelFmt, // Format of the pixelBuffer
Igor Murashkin5096def2014-06-24 10:49:11 -0700164 int32_t bufSize) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700165 ATRACE_CALL();
166 status_t err = NO_ERROR;
167 ANativeWindowBuffer* anb;
Igor Murashkin5096def2014-06-24 10:49:11 -0700168 ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
Ruben Brunk31798f32014-09-25 19:56:54 -0700169 __FUNCTION__, anw.get(), bufWidth, bufHeight, pixelFmt, bufSize);
Igor Murashkin5096def2014-06-24 10:49:11 -0700170
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;
Ruben Brunk31798f32014-09-25 19:56:54 -0700177 } else if (bufWidth < 0) {
Igor Murashkin5096def2014-06-24 10:49:11 -0700178 ALOGE("%s: width must be non-negative", __FUNCTION__);
179 return BAD_VALUE;
Ruben Brunk31798f32014-09-25 19:56:54 -0700180 } else if (bufHeight < 0) {
Igor Murashkin5096def2014-06-24 10:49:11 -0700181 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 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700187
Ruben Brunk31798f32014-09-25 19:56:54 -0700188 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);
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700191
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700192 // 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));
Ruben Brunk0c798842014-09-30 03:42:13 -0700197 uint32_t grallocBufWidth = buf->getWidth();
198 uint32_t grallocBufHeight = buf->getHeight();
199 uint32_t grallocBufStride = buf->getStride();
200 if (grallocBufWidth != width || grallocBufHeight != height) {
Ruben Brunk31798f32014-09-25 19:56:54 -0700201 ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32
Ruben Brunk0c798842014-09-30 03:42:13 -0700202 ", expecting dimensions %zu x %zu", __FUNCTION__, grallocBufWidth,
203 grallocBufHeight, width, height);
Ruben Brunk31798f32014-09-25 19:56:54 -0700204 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
Ruben Brunk0c798842014-09-30 03:42:13 -0700215 uint64_t tmpSize = (pixelFmt == HAL_PIXEL_FORMAT_BLOB) ? grallocBufWidth :
216 4 * grallocBufHeight * grallocBufWidth;
Ruben Brunk31798f32014-09-25 19:56:54 -0700217 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__);
Ruben Brunk0c798842014-09-30 03:42:13 -0700220 tmpSize = 4 * (grallocBufWidth + grallocBufStride * (grallocBufHeight - 1));
Ruben Brunk31798f32014-09-25 19:56:54 -0700221 } 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;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700234
Ruben Brunk433e7152014-12-10 19:12:41 -0800235 ALOGV("%s: Pixel format chosen: %x", __FUNCTION__, pixelFmt);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700236 switch(pixelFmt) {
237 case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
Ruben Brunk31798f32014-09-25 19:56:54 -0700238 if (bufferLength < totalSizeBytes) {
239 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
240 __FUNCTION__, bufferLength);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700241 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 }
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700259 case HAL_PIXEL_FORMAT_YV12: {
Ruben Brunk31798f32014-09-25 19:56:54 -0700260 if (bufferLength < totalSizeBytes) {
261 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
262 __FUNCTION__, bufferLength);
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700263 return BAD_VALUE;
264 }
265
266 if ((width & 1) || (height & 1)) {
Ruben Brunk31798f32014-09-25 19:56:54 -0700267 ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height);
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700268 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();
Ruben Brunk433e7152014-12-10 19:12:41 -0800281 ALOGV("%s: stride is: %" PRIu32, __FUNCTION__, stride);
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700282 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 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700295 case HAL_PIXEL_FORMAT_YCbCr_420_888: {
296 // Software writes with YCbCr_420_888 format are unsupported
297 // by the gralloc module for now
Ruben Brunk31798f32014-09-25 19:56:54 -0700298 if (bufferLength < totalSizeBytes) {
299 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
300 __FUNCTION__, bufferLength);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700301 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: {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700316 int8_t* img = NULL;
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700317 struct camera3_jpeg_blob footer = {
Bernhard Rosenkränzer452efb22014-11-17 23:42:21 +0100318 .jpeg_blob_id = CAMERA3_JPEG_BLOB_ID,
319 .jpeg_size = (uint32_t)bufferLength
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700320 };
321
Ruben Brunk31798f32014-09-25 19:56:54 -0700322 size_t totalJpegSize = bufferLength + sizeof(footer);
323 totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble
324
Ruben Brunk31798f32014-09-25 19:56:54 -0700325 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
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700331 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 }
Ruben Brunk31798f32014-09-25 19:56:54 -0700337
338 memcpy(img, pixelBuffer, bufferLength);
339 memcpy(img + totalSizeBytes - sizeof(footer), &footer, sizeof(footer));
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700340 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()) {
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700369 return NULL;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700370 }
371 } else {
372 jniThrowNullPointerException(env, "surface");
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700373 return NULL;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700374 }
375 if (anw == NULL) {
376 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
377 "Surface had no valid native window.");
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700378 return NULL;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700379 }
380 return anw;
381}
382
Ruben Brunk28c49c92014-06-16 18:43:59 -0700383static sp<ANativeWindow> getNativeWindowFromTexture(JNIEnv* env, jobject surfaceTexture) {
384 sp<ANativeWindow> anw;
385 if (surfaceTexture) {
386 anw = android_SurfaceTexture_getNativeWindow(env, surfaceTexture);
387 if (env->ExceptionCheck()) {
388 return NULL;
389 }
390 } else {
391 jniThrowNullPointerException(env, "surfaceTexture");
392 return NULL;
393 }
394 if (anw == NULL) {
395 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
396 "SurfaceTexture had no valid native window.");
397 return NULL;
398 }
399 return anw;
400}
401
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700402static sp<Surface> getSurface(JNIEnv* env, jobject surface) {
403 sp<Surface> s;
404 if (surface) {
405 s = android_view_Surface_getSurface(env, surface);
406 if (env->ExceptionCheck()) {
407 return NULL;
408 }
409 } else {
410 jniThrowNullPointerException(env, "surface");
411 return NULL;
412 }
413 if (s == NULL) {
414 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
415 "Surface had no valid native Surface.");
416 return NULL;
417 }
418 return s;
419}
420
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700421extern "C" {
422
423static jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) {
424 ALOGV("nativeDetectSurfaceType");
425 sp<ANativeWindow> anw;
426 if ((anw = getNativeWindow(env, surface)) == NULL) {
427 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700428 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700429 }
430 int32_t fmt = 0;
431 status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt);
432 if(err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700433 ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err),
434 err);
435 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700436 }
437 return fmt;
438}
439
Ruben Brunkef14da32014-06-24 16:06:54 -0700440static jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700441 jobject surface, jintArray dimens) {
442 ALOGV("nativeGetSurfaceDimens");
Ruben Brunk28c49c92014-06-16 18:43:59 -0700443
444 if (dimens == NULL) {
445 ALOGE("%s: Null dimens argument passed to nativeDetectSurfaceDimens", __FUNCTION__);
446 return BAD_VALUE;
447 }
448
449 if (env->GetArrayLength(dimens) < 2) {
450 ALOGE("%s: Invalid length of dimens argument in nativeDetectSurfaceDimens", __FUNCTION__);
451 return BAD_VALUE;
452 }
453
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700454 sp<ANativeWindow> anw;
455 if ((anw = getNativeWindow(env, surface)) == NULL) {
456 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700457 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700458 }
459 int32_t dimenBuf[2];
460 status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
461 if(err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700462 ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err),
463 err);
464 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700465 }
466 err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
467 if(err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700468 ALOGE("%s: Error while querying surface height %s (%d).", __FUNCTION__, strerror(-err),
469 err);
470 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700471 }
472 env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
Ruben Brunkef14da32014-06-24 16:06:54 -0700473 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700474}
475
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800476static jint LegacyCameraDevice_nativeDetectSurfaceUsageFlags(JNIEnv* env, jobject thiz,
477 jobject surface) {
478 ALOGV("nativeDetectSurfaceUsageFlags");
479
480 sp<ANativeWindow> anw;
481 if ((anw = getNativeWindow(env, surface)) == NULL) {
482 jniThrowException(env, "Ljava/lang/UnsupportedOperationException;",
483 "Could not retrieve native window from surface.");
484 return BAD_VALUE;
485 }
486 int32_t usage = 0;
487 status_t err = anw->query(anw.get(), NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
488 if(err != NO_ERROR) {
489 jniThrowException(env, "Ljava/lang/UnsupportedOperationException;",
490 "Error while querying surface usage bits");
491 return err;
492 }
493 return usage;
494}
495
Ruben Brunk28c49c92014-06-16 18:43:59 -0700496static jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz,
497 jobject surfaceTexture, jintArray dimens) {
498 ALOGV("nativeDetectTextureDimens");
499 sp<ANativeWindow> anw;
500 if ((anw = getNativeWindowFromTexture(env, surfaceTexture)) == NULL) {
501 ALOGE("%s: Could not retrieve native window from SurfaceTexture.", __FUNCTION__);
502 return BAD_VALUE;
503 }
504
505 int32_t dimenBuf[2];
506 status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
507 if(err != NO_ERROR) {
508 ALOGE("%s: Error while querying SurfaceTexture width %s (%d)", __FUNCTION__,
509 strerror(-err), err);
510 return err;
511 }
512
513 err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
514 if(err != NO_ERROR) {
515 ALOGE("%s: Error while querying SurfaceTexture height %s (%d)", __FUNCTION__,
516 strerror(-err), err);
517 return err;
518 }
519
520 env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
521 if (env->ExceptionCheck()) {
522 return BAD_VALUE;
523 }
524 return NO_ERROR;
525}
526
Ruben Brunkef14da32014-06-24 16:06:54 -0700527static jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700528 jint width, jint height, jint pixelFormat) {
529 ALOGV("nativeConfigureSurface");
530 sp<ANativeWindow> anw;
531 if ((anw = getNativeWindow(env, surface)) == NULL) {
532 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700533 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700534 }
535 status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK);
536 if (err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700537 ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
538 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700539 }
Ruben Brunkef14da32014-06-24 16:06:54 -0700540 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700541}
542
Ruben Brunkef14da32014-06-24 16:06:54 -0700543static jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700544 jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) {
545 ALOGV("nativeProduceFrame");
546 sp<ANativeWindow> anw;
547
548 if ((anw = getNativeWindow(env, surface)) == NULL) {
549 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700550 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700551 }
552
553 if (pixelBuffer == NULL) {
554 jniThrowNullPointerException(env, "pixelBuffer");
Ruben Brunkef14da32014-06-24 16:06:54 -0700555 return DONT_CARE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700556 }
557
558 int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer));
559 jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL);
560
561 if (pixels == NULL) {
562 jniThrowNullPointerException(env, "pixels");
Ruben Brunkef14da32014-06-24 16:06:54 -0700563 return DONT_CARE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700564 }
565
566 status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height,
567 pixelFormat, bufSize);
568 env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT);
569
570 if (err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700571 ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err);
572 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700573 }
Ruben Brunkef14da32014-06-24 16:06:54 -0700574 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700575}
576
Ruben Brunkef14da32014-06-24 16:06:54 -0700577static jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700578 jint pixelFormat) {
579 ALOGV("nativeSetSurfaceType");
580 sp<ANativeWindow> anw;
581 if ((anw = getNativeWindow(env, surface)) == NULL) {
582 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700583 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700584 }
585 status_t err = native_window_set_buffers_format(anw.get(), pixelFormat);
586 if (err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700587 ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err);
588 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700589 }
Ruben Brunkef14da32014-06-24 16:06:54 -0700590 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700591}
592
Ruben Brunkef14da32014-06-24 16:06:54 -0700593static jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700594 jint width, jint height) {
595 ALOGV("nativeSetSurfaceDimens");
596 sp<ANativeWindow> anw;
597 if ((anw = getNativeWindow(env, surface)) == NULL) {
598 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700599 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700600 }
Ruben Brunka9bc3552014-08-14 15:57:28 -0700601
Eino-Ville Talvalab0acf7f2015-02-11 15:41:12 -0800602 // Set user dimensions only
603 // The producer dimensions are owned by GL
604 status_t err = native_window_set_buffers_user_dimensions(anw.get(), width, height);
Ruben Brunka9bc3552014-08-14 15:57:28 -0700605 if (err != NO_ERROR) {
606 ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err),
607 err);
608 return err;
609 }
Ruben Brunkef14da32014-06-24 16:06:54 -0700610 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700611}
612
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700613static jlong LegacyCameraDevice_nativeGetSurfaceId(JNIEnv* env, jobject thiz, jobject surface) {
614 ALOGV("nativeGetSurfaceId");
615 sp<Surface> s;
616 if ((s = getSurface(env, surface)) == NULL) {
617 ALOGE("%s: Could not retrieve native Surface from surface.", __FUNCTION__);
618 return 0;
619 }
620 sp<IGraphicBufferProducer> gbp = s->getIGraphicBufferProducer();
621 if (gbp == NULL) {
622 ALOGE("%s: Could not retrieve IGraphicBufferProducer from surface.", __FUNCTION__);
623 return 0;
624 }
Marco Nelissen97069dd2014-11-14 08:00:42 -0800625 sp<IBinder> b = IInterface::asBinder(gbp);
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700626 if (b == NULL) {
627 ALOGE("%s: Could not retrieve IBinder from surface.", __FUNCTION__);
628 return 0;
629 }
630 /*
631 * FIXME: Use better unique ID for surfaces than native IBinder pointer. Fix also in the camera
632 * service (CameraDeviceClient.h).
633 */
634 return reinterpret_cast<jlong>(b.get());
635}
636
Ruben Brunk28c49c92014-06-16 18:43:59 -0700637static jint LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv* env, jobject thiz,
638 jobject surface, jint facing, jint orientation) {
639 ALOGV("nativeSetSurfaceOrientation");
640 sp<ANativeWindow> anw;
641 if ((anw = getNativeWindow(env, surface)) == NULL) {
642 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
643 return BAD_VALUE;
644 }
645
646 status_t err = NO_ERROR;
647 CameraMetadata staticMetadata;
648
649 int32_t orientVal = static_cast<int32_t>(orientation);
650 uint8_t facingVal = static_cast<uint8_t>(facing);
651 staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1);
652 staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1);
653
654 int32_t transform = 0;
655
Ruben Brunk91838de2014-07-16 17:24:17 -0700656 if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) {
Ruben Brunk28c49c92014-06-16 18:43:59 -0700657 ALOGE("%s: Invalid rotation transform %s (%d)", __FUNCTION__, strerror(-err),
658 err);
659 return err;
660 }
661
662 ALOGV("%s: Setting buffer sticky transform to %d", __FUNCTION__, transform);
663
Ruben Brunk91838de2014-07-16 17:24:17 -0700664 if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) {
Ruben Brunk28c49c92014-06-16 18:43:59 -0700665 ALOGE("%s: Unable to configure surface transform, error %s (%d)", __FUNCTION__,
666 strerror(-err), err);
667 return err;
668 }
669
670 return NO_ERROR;
671}
672
Ruben Brunk91838de2014-07-16 17:24:17 -0700673static jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz, jobject surface,
674 jlong timestamp) {
675 ALOGV("nativeSetNextTimestamp");
676 sp<ANativeWindow> anw;
677 if ((anw = getNativeWindow(env, surface)) == NULL) {
678 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
679 return BAD_VALUE;
680 }
681
682 status_t err = NO_ERROR;
683
684 if ((err = native_window_set_buffers_timestamp(anw.get(), static_cast<int64_t>(timestamp))) !=
685 NO_ERROR) {
686 ALOGE("%s: Unable to set surface timestamp, error %s (%d)", __FUNCTION__, strerror(-err),
687 err);
688 return err;
689 }
690 return NO_ERROR;
691}
692
Ruben Brunk1dc13262014-07-31 11:43:27 -0700693static jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) {
694 ALOGV("nativeGetJpegFooterSize");
695 return static_cast<jint>(sizeof(struct camera3_jpeg_blob));
696}
697
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700698} // extern "C"
699
700static JNINativeMethod gCameraDeviceMethods[] = {
701 { "nativeDetectSurfaceType",
702 "(Landroid/view/Surface;)I",
703 (void *)LegacyCameraDevice_nativeDetectSurfaceType },
704 { "nativeDetectSurfaceDimens",
Ruben Brunkef14da32014-06-24 16:06:54 -0700705 "(Landroid/view/Surface;[I)I",
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700706 (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
707 { "nativeConfigureSurface",
Ruben Brunkef14da32014-06-24 16:06:54 -0700708 "(Landroid/view/Surface;III)I",
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700709 (void *)LegacyCameraDevice_nativeConfigureSurface },
710 { "nativeProduceFrame",
Ruben Brunkef14da32014-06-24 16:06:54 -0700711 "(Landroid/view/Surface;[BIII)I",
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700712 (void *)LegacyCameraDevice_nativeProduceFrame },
713 { "nativeSetSurfaceFormat",
Ruben Brunkef14da32014-06-24 16:06:54 -0700714 "(Landroid/view/Surface;I)I",
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700715 (void *)LegacyCameraDevice_nativeSetSurfaceFormat },
716 { "nativeSetSurfaceDimens",
Ruben Brunkef14da32014-06-24 16:06:54 -0700717 "(Landroid/view/Surface;II)I",
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700718 (void *)LegacyCameraDevice_nativeSetSurfaceDimens },
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700719 { "nativeGetSurfaceId",
720 "(Landroid/view/Surface;)J",
721 (void *)LegacyCameraDevice_nativeGetSurfaceId },
Ruben Brunk28c49c92014-06-16 18:43:59 -0700722 { "nativeDetectTextureDimens",
723 "(Landroid/graphics/SurfaceTexture;[I)I",
724 (void *)LegacyCameraDevice_nativeDetectTextureDimens },
725 { "nativeSetSurfaceOrientation",
726 "(Landroid/view/Surface;II)I",
727 (void *)LegacyCameraDevice_nativeSetSurfaceOrientation },
Ruben Brunk91838de2014-07-16 17:24:17 -0700728 { "nativeSetNextTimestamp",
729 "(Landroid/view/Surface;J)I",
730 (void *)LegacyCameraDevice_nativeSetNextTimestamp },
Ruben Brunk1dc13262014-07-31 11:43:27 -0700731 { "nativeGetJpegFooterSize",
732 "()I",
733 (void *)LegacyCameraDevice_nativeGetJpegFooterSize },
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800734 { "nativeDetectSurfaceUsageFlags",
735 "(Landroid/view/Surface;)I",
736 (void *)LegacyCameraDevice_nativeDetectSurfaceUsageFlags },
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700737};
738
739// Get all the required offsets in java class and register native functions
740int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env)
741{
742 // Register native functions
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800743 return RegisterMethodsOrDie(env,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700744 CAMERA_DEVICE_CLASS_NAME,
745 gCameraDeviceMethods,
746 NELEM(gCameraDeviceMethods));
747}