• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
40 using 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  */
rgbToYuv420(uint8_t * rgbBuf,size_t width,size_t height,uint8_t * yPlane,uint8_t * uPlane,uint8_t * vPlane,size_t chromaStep,size_t yStride,size_t chromaStride)54 static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane,
55         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;
58     for (size_t j = 0; j < height; j++) {
59         uint8_t* u = uPlane;
60         uint8_t* v = vPlane;
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                 *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;
73             }
74             // Skip alpha
75             index++;
76         }
77         yPlane += yStride;
78         if (jEven) {
79             uPlane += chromaStride;
80             vPlane += chromaStride;
81         }
82     }
83 }
84 
rgbToYuv420(uint8_t * rgbBuf,size_t width,size_t height,android_ycbcr * ycbcr)85 static 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 
configureSurface(const sp<ANativeWindow> & anw,int32_t width,int32_t height,int32_t pixelFmt,int32_t maxBufferSlack)96 static 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  */
produceFrame(const sp<ANativeWindow> & anw,uint8_t * pixelBuffer,int32_t bufWidth,int32_t bufHeight,int32_t pixelFmt,int32_t bufSize)159 static 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 
getNativeWindow(JNIEnv * env,jobject surface)364 static 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         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
377                 "Surface had no valid native window.");
378         return NULL;
379     }
380     return anw;
381 }
382 
getNativeWindowFromTexture(JNIEnv * env,jobject surfaceTexture)383 static 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 
getSurface(JNIEnv * env,jobject surface)402 static 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 
421 extern "C" {
422 
LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv * env,jobject thiz,jobject surface)423 static 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__);
428         return BAD_VALUE;
429     }
430     int32_t fmt = 0;
431     status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt);
432     if(err != NO_ERROR) {
433         ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err),
434                 err);
435         return err;
436     }
437     return fmt;
438 }
439 
LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv * env,jobject thiz,jobject surface,jintArray dimens)440 static jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz,
441           jobject surface, jintArray dimens) {
442     ALOGV("nativeGetSurfaceDimens");
443 
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 
454     sp<ANativeWindow> anw;
455     if ((anw = getNativeWindow(env, surface)) == NULL) {
456         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
457         return BAD_VALUE;
458     }
459     int32_t dimenBuf[2];
460     status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
461     if(err != NO_ERROR) {
462         ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err),
463                 err);
464         return err;
465     }
466     err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
467     if(err != NO_ERROR) {
468         ALOGE("%s: Error while querying surface height %s (%d).", __FUNCTION__, strerror(-err),
469                 err);
470         return err;
471     }
472     env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
473     return NO_ERROR;
474 }
475 
LegacyCameraDevice_nativeDetectSurfaceUsageFlags(JNIEnv * env,jobject thiz,jobject surface)476 static 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 
LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv * env,jobject thiz,jobject surfaceTexture,jintArray dimens)496 static 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 
LegacyCameraDevice_nativeConfigureSurface(JNIEnv * env,jobject thiz,jobject surface,jint width,jint height,jint pixelFormat)527 static jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface,
528         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__);
533         return BAD_VALUE;
534     }
535     status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK);
536     if (err != NO_ERROR) {
537         ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
538         return err;
539     }
540     return NO_ERROR;
541 }
542 
LegacyCameraDevice_nativeProduceFrame(JNIEnv * env,jobject thiz,jobject surface,jbyteArray pixelBuffer,jint width,jint height,jint pixelFormat)543 static jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface,
544         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__);
550         return BAD_VALUE;
551     }
552 
553     if (pixelBuffer == NULL) {
554         jniThrowNullPointerException(env, "pixelBuffer");
555         return DONT_CARE;
556     }
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");
563         return DONT_CARE;
564     }
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) {
571         ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err);
572         return err;
573     }
574     return NO_ERROR;
575 }
576 
LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv * env,jobject thiz,jobject surface,jint pixelFormat)577 static jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface,
578         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__);
583         return BAD_VALUE;
584     }
585     status_t err = native_window_set_buffers_format(anw.get(), pixelFormat);
586     if (err != NO_ERROR) {
587         ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err);
588         return err;
589     }
590     return NO_ERROR;
591 }
592 
LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv * env,jobject thiz,jobject surface,jint width,jint height)593 static jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface,
594         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__);
599         return BAD_VALUE;
600     }
601 
602     // 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);
605     if (err != NO_ERROR) {
606         ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err),
607                 err);
608         return err;
609     }
610     return NO_ERROR;
611 }
612 
LegacyCameraDevice_nativeGetSurfaceId(JNIEnv * env,jobject thiz,jobject surface)613 static 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     }
625     sp<IBinder> b = gbp->asBinder();
626     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 
LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv * env,jobject thiz,jobject surface,jint facing,jint orientation)637 static 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 
656     if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) {
657         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 
664     if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) {
665         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 
LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv * env,jobject thiz,jobject surface,jlong timestamp)673 static 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 
LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv * env,jobject thiz)693 static jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) {
694     ALOGV("nativeGetJpegFooterSize");
695     return static_cast<jint>(sizeof(struct camera3_jpeg_blob));
696 }
697 
698 } // extern "C"
699 
700 static JNINativeMethod gCameraDeviceMethods[] = {
701     { "nativeDetectSurfaceType",
702     "(Landroid/view/Surface;)I",
703     (void *)LegacyCameraDevice_nativeDetectSurfaceType },
704     { "nativeDetectSurfaceDimens",
705     "(Landroid/view/Surface;[I)I",
706     (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
707     { "nativeConfigureSurface",
708     "(Landroid/view/Surface;III)I",
709     (void *)LegacyCameraDevice_nativeConfigureSurface },
710     { "nativeProduceFrame",
711     "(Landroid/view/Surface;[BIII)I",
712     (void *)LegacyCameraDevice_nativeProduceFrame },
713     { "nativeSetSurfaceFormat",
714     "(Landroid/view/Surface;I)I",
715     (void *)LegacyCameraDevice_nativeSetSurfaceFormat },
716     { "nativeSetSurfaceDimens",
717     "(Landroid/view/Surface;II)I",
718     (void *)LegacyCameraDevice_nativeSetSurfaceDimens },
719     { "nativeGetSurfaceId",
720     "(Landroid/view/Surface;)J",
721     (void *)LegacyCameraDevice_nativeGetSurfaceId },
722     { "nativeDetectTextureDimens",
723     "(Landroid/graphics/SurfaceTexture;[I)I",
724     (void *)LegacyCameraDevice_nativeDetectTextureDimens },
725     { "nativeSetSurfaceOrientation",
726     "(Landroid/view/Surface;II)I",
727     (void *)LegacyCameraDevice_nativeSetSurfaceOrientation },
728     { "nativeSetNextTimestamp",
729     "(Landroid/view/Surface;J)I",
730     (void *)LegacyCameraDevice_nativeSetNextTimestamp },
731     { "nativeGetJpegFooterSize",
732     "()I",
733     (void *)LegacyCameraDevice_nativeGetJpegFooterSize },
734     { "nativeDetectSurfaceUsageFlags",
735     "(Landroid/view/Surface;)I",
736     (void *)LegacyCameraDevice_nativeDetectSurfaceUsageFlags },
737 };
738 
739 // Get all the required offsets in java class and register native functions
register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv * env)740 int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env)
741 {
742     // Register native functions
743     return AndroidRuntime::registerNativeMethods(env,
744             CAMERA_DEVICE_CLASS_NAME,
745             gCameraDeviceMethods,
746             NELEM(gCameraDeviceMethods));
747 }
748