android_hardware_camera2_legacy_LegacyCameraDevice.cpp revision 8973597944890db9e7ad90a29ff8a44e6b2e2a7b
1feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/*
2feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Copyright (C) 2014 The Android Open Source Project
3feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
4feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
5feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * you may not use this file except in compliance with the License.
6feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * You may obtain a copy of the License at
7feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
8feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *      http://www.apache.org/licenses/LICENSE-2.0
9feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
10feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Unless required by applicable law or agreed to in writing, software
11feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
12feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * See the License for the specific language governing permissions and
14feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * limitations under the License.
15feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
16feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
17feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#define LOG_TAG "Legacy-CameraDevice-JNI"
185096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin// #define LOG_NDEBUG 0
19feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include <utils/Log.h>
20feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include <utils/Errors.h>
21feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include <utils/Trace.h>
2228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk#include <camera/CameraUtils.h>
23feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
24feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include "jni.h"
25feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include "JNIHelp.h"
26ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
27feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include "android_runtime/android_view_Surface.h"
2828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk#include "android_runtime/android_graphics_SurfaceTexture.h"
29feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
303c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk#include <gui/Surface.h>
313c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk#include <gui/IGraphicBufferProducer.h>
32feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include <ui/GraphicBuffer.h>
33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include <system/window.h>
345096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin#include <hardware/camera3.h>
3528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk#include <system/camera_metadata.h>
36feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
373c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk#include <stdint.h>
383c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk#include <inttypes.h>
393c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
40feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkusing namespace android;
41feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
42feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk// fully-qualified class name
43feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#define CAMERA_DEVICE_CLASS_NAME "android/hardware/camera2/legacy/LegacyCameraDevice"
44feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#define CAMERA_DEVICE_BUFFER_SLACK  3
45ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk#define DONT_CARE 0
46feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
47feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
48feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
4991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
5091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
52433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk * Convert from RGB 888 to Y'CbCr using the conversion specified in JFIF v1.02
53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
5431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunkstatic void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane,
558973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk        uint8_t* crPlane, uint8_t* cbPlane, size_t chromaStep, size_t yStride, size_t chromaStride) {
56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    uint8_t R, G, B;
57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    size_t index = 0;
5831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    for (size_t j = 0; j < height; j++) {
598973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk        uint8_t* cr = crPlane;
608973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk        uint8_t* cb = cbPlane;
61433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk        uint8_t* y = yPlane;
62433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk        bool jEven = (j & 1) == 0;
6331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        for (size_t i = 0; i < width; i++) {
64feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            R = rgbBuf[index++];
65feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            G = rgbBuf[index++];
66feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            B = rgbBuf[index++];
67433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk            *y++ = (77 * R + 150 * G +  29 * B) >> 8;
68433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk            if (jEven && (i & 1) == 0) {
698973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk                *cb = (( -43 * R - 85 * G + 128 * B) >> 8) + 128;
708973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk                *cr = (( 128 * R - 107 * G - 21 * B) >> 8) + 128;
718973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk                cr += chromaStep;
728973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk                cb += chromaStep;
73feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
74feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // Skip alpha
75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            index++;
76feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
77feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        yPlane += yStride;
78433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk        if (jEven) {
798973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk            crPlane += chromaStride;
808973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk            cbPlane += chromaStride;
81feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
82feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
83feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
84feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
8531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunkstatic void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, android_ycbcr* ycbcr) {
86feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    size_t cStep = ycbcr->chroma_step;
87feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    size_t cStride = ycbcr->cstride;
88feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    size_t yStride = ycbcr->ystride;
89433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk    ALOGV("%s: yStride is: %zu, cStride is: %zu, cStep is: %zu", __FUNCTION__, yStride, cStride,
90433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk            cStep);
91feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    rgbToYuv420(rgbBuf, width, height, reinterpret_cast<uint8_t*>(ycbcr->y),
92433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk            reinterpret_cast<uint8_t*>(ycbcr->cr), reinterpret_cast<uint8_t*>(ycbcr->cb),
93feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            cStep, yStride, cStride);
94feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
95feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
96feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic status_t configureSurface(const sp<ANativeWindow>& anw,
97feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 int32_t width,
98feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 int32_t height,
99feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 int32_t pixelFmt,
100feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 int32_t maxBufferSlack) {
101feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = NO_ERROR;
102feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_set_buffers_dimensions(anw.get(), width, height);
103feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
104feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window buffer dimensions, error %s (%d).", __FUNCTION__,
105feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
106feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
107feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
108feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
109feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_set_buffers_format(anw.get(), pixelFmt);
110feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
111feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window buffer format, error %s (%d).", __FUNCTION__,
112feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
113feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
114feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
115feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
116feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
117feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
118feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__,
119feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
120feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
121feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
122feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
123feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int minUndequeuedBuffers;
124feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = anw.get()->query(anw.get(),
125feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
126feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            &minUndequeuedBuffers);
127feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
128feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).",
129feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                __FUNCTION__, strerror(-err), err);
130feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
131feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
132feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
1335096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    ALOGV("%s: Setting buffer count to %d, size to (%dx%d), fmt (0x%x)", __FUNCTION__,
1345096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin          maxBufferSlack + 1 + minUndequeuedBuffers,
1355096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin          width, height, pixelFmt);
136feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_set_buffer_count(anw.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
137feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
138feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
139feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
140feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
141feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
142feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return NO_ERROR;
143feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
144feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
145feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
146feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Produce a frame in the given surface.
147feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
148feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Args:
149feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    anw - a surface to produce a frame in.
150feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    pixelBuffer - image buffer to generate a frame from.
151feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    width - width of the pixelBuffer in pixels.
152feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    height - height of the pixelBuffer in pixels.
153feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    pixelFmt - format of the pixelBuffer, one of:
154feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *               HAL_PIXEL_FORMAT_YCrCb_420_SP,
155feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *               HAL_PIXEL_FORMAT_YCbCr_420_888,
156feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *               HAL_PIXEL_FORMAT_BLOB
157feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    bufSize - the size of the pixelBuffer in bytes.
158feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
159feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic status_t produceFrame(const sp<ANativeWindow>& anw,
160feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                             uint8_t* pixelBuffer,
16131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                             int32_t bufWidth, // Width of the pixelBuffer
16231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                             int32_t bufHeight, // Height of the pixelBuffer
163feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                             int32_t pixelFmt, // Format of the pixelBuffer
1645096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin                             int32_t bufSize) {
165feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ATRACE_CALL();
166feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = NO_ERROR;
167feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ANativeWindowBuffer* anb;
1685096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
16931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            __FUNCTION__, anw.get(), bufWidth, bufHeight, pixelFmt, bufSize);
1705096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin
1715096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    if (anw == 0) {
1725096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: anw must not be NULL", __FUNCTION__);
1735096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
1745096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    } else if (pixelBuffer == NULL) {
1755096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__);
1765096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
17731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    } else if (bufWidth < 0) {
1785096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: width must be non-negative", __FUNCTION__);
1795096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
18031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    } else if (bufHeight < 0) {
1815096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: height must be non-negative", __FUNCTION__);
1825096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
1835096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    } else if (bufSize < 0) {
1845096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: bufSize must be non-negative", __FUNCTION__);
1855096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
1865096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    }
187feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
18831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t width = static_cast<size_t>(bufWidth);
18931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t height = static_cast<size_t>(bufHeight);
19031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t bufferLength = static_cast<size_t>(bufSize);
19191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
192feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // TODO: Switch to using Surface::lock and Surface::unlockAndPost
193feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
194feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) return err;
195feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
196feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));
1970c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    uint32_t grallocBufWidth = buf->getWidth();
1980c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    uint32_t grallocBufHeight = buf->getHeight();
1990c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    uint32_t grallocBufStride = buf->getStride();
2000c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    if (grallocBufWidth != width || grallocBufHeight != height) {
20131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32
2020c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk                ", expecting dimensions %zu x %zu",  __FUNCTION__, grallocBufWidth,
2030c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk                grallocBufHeight, width, height);
20431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        return BAD_VALUE;
20531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
20631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
20731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    int32_t bufFmt = 0;
20831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &bufFmt);
20931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    if (err != NO_ERROR) {
21031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__,
21131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                strerror(-err), err);
21231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        return err;
21331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
21431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
2150c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    uint64_t tmpSize = (pixelFmt == HAL_PIXEL_FORMAT_BLOB) ? grallocBufWidth :
2160c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk            4 * grallocBufHeight * grallocBufWidth;
21731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    if (bufFmt != pixelFmt) {
21831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        if (bufFmt == HAL_PIXEL_FORMAT_RGBA_8888 && pixelFmt == HAL_PIXEL_FORMAT_BLOB) {
21931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            ALOGV("%s: Using BLOB to RGBA format override.", __FUNCTION__);
2200c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk            tmpSize = 4 * (grallocBufWidth + grallocBufStride * (grallocBufHeight - 1));
22131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        } else {
22231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            ALOGW("%s: Format mismatch in produceFrame: expecting format %#" PRIx32
22331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                    ", but received buffer with format %#" PRIx32, __FUNCTION__, pixelFmt, bufFmt);
22431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        }
22531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
22631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
22731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    if (tmpSize > SIZE_MAX) {
22831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        ALOGE("%s: Overflow calculating size, buffer with dimens %zu x %zu is absurdly large...",
22931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                __FUNCTION__, width, height);
23031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        return BAD_VALUE;
23131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
23231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
23331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t totalSizeBytes = tmpSize;
234feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
235433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk    ALOGV("%s: Pixel format chosen: %x", __FUNCTION__, pixelFmt);
236feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    switch(pixelFmt) {
237feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
23831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (bufferLength < totalSizeBytes) {
23931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
24031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, bufferLength);
241feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return BAD_VALUE;
242feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
243feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* img = NULL;
244feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
245feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
246feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (err != NO_ERROR) return err;
247feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
248feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* yPlane = img;
249feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* uPlane = img + height * width;
250feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* vPlane = uPlane + 1;
251feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            size_t chromaStep = 2;
252feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            size_t yStride = width;
253feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            size_t chromaStride = width;
254feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
255feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            rgbToYuv420(pixelBuffer, width, height, yPlane,
256feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    uPlane, vPlane, chromaStep, yStride, chromaStride);
257feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            break;
258feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
25991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk        case HAL_PIXEL_FORMAT_YV12: {
26031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (bufferLength < totalSizeBytes) {
26131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
26231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, bufferLength);
26391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                return BAD_VALUE;
26491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            }
26591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
26691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            if ((width & 1) || (height & 1)) {
26731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height);
26891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                return BAD_VALUE;
26991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            }
27091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
27191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* img = NULL;
27291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
27391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
27491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            if (err != NO_ERROR) {
27591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                ALOGE("%s: Error %s (%d) while locking gralloc buffer for write.", __FUNCTION__,
27691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                        strerror(-err), err);
27791b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                return err;
27891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            }
27991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
28091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint32_t stride = buf->getStride();
281433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk            ALOGV("%s: stride is: %" PRIu32, __FUNCTION__, stride);
28291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            LOG_ALWAYS_FATAL_IF(stride % 16, "Stride is not 16 pixel aligned %d", stride);
28391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
28491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint32_t cStride = ALIGN(stride / 2, 16);
28591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            size_t chromaStep = 1;
28691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
28791b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* yPlane = img;
28891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* crPlane = img + static_cast<uint32_t>(height) * stride;
28991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* cbPlane = crPlane + cStride * static_cast<uint32_t>(height) / 2;
29091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
29191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            rgbToYuv420(pixelBuffer, width, height, yPlane,
29291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                    crPlane, cbPlane, chromaStep, stride, cStride);
29391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            break;
29491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk        }
295feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        case HAL_PIXEL_FORMAT_YCbCr_420_888: {
296feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // Software writes with YCbCr_420_888 format are unsupported
297feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // by the gralloc module for now
29831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (bufferLength < totalSizeBytes) {
29931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
30031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, bufferLength);
301feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return BAD_VALUE;
302feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
303feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            android_ycbcr ycbcr = android_ycbcr();
304feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
305feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
306feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            err = buf->lockYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr);
307feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (err != NO_ERROR) {
308feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                ALOGE("%s: Failed to lock ycbcr buffer, error %s (%d).", __FUNCTION__,
309feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        strerror(-err), err);
310feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return err;
311feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
312feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            rgbToYuv420(pixelBuffer, width, height, &ycbcr);
313feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            break;
314feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
315feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        case HAL_PIXEL_FORMAT_BLOB: {
316feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int8_t* img = NULL;
3170fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk            struct camera3_jpeg_blob footer = {
318452efb218eb9af6ab2763879645bfc92db8ba02aBernhard Rosenkränzer                .jpeg_blob_id = CAMERA3_JPEG_BLOB_ID,
319452efb218eb9af6ab2763879645bfc92db8ba02aBernhard Rosenkränzer                .jpeg_size = (uint32_t)bufferLength
3200fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk            };
3210fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk
32231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            size_t totalJpegSize = bufferLength + sizeof(footer);
32331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble
32431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
32531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (totalJpegSize > totalSizeBytes) {
32631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: Pixel buffer needs size %zu, cannot fit in gralloc buffer of size %zu",
32731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, totalJpegSize, totalSizeBytes);
3280fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk                return BAD_VALUE;
3290fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk            }
330feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
331feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
332feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (err != NO_ERROR) {
333feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                ALOGE("%s: Failed to lock buffer, error %s (%d).", __FUNCTION__, strerror(-err),
334feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        err);
335feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return err;
336feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
33731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
33831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            memcpy(img, pixelBuffer, bufferLength);
33931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            memcpy(img + totalSizeBytes - sizeof(footer), &footer, sizeof(footer));
340feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            break;
341feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
342feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        default: {
343feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            ALOGE("%s: Invalid pixel format in produceFrame: %x", __FUNCTION__, pixelFmt);
344feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            return BAD_VALUE;
345feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
346feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
347feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
348feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("%s: Unlock buffer from %p", __FUNCTION__, anw.get());
349feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = buf->unlock();
350feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
351feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to unlock buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
352feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
353feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
354feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
355feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("%s: Queue buffer to %p", __FUNCTION__, anw.get());
356feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), /*fenceFd*/-1);
357feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
358feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to queue buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
359feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
360feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
361feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return NO_ERROR;
362feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
363feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
364feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic sp<ANativeWindow> getNativeWindow(JNIEnv* env, jobject surface) {
365feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
366feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (surface) {
367feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        anw = android_view_Surface_getNativeWindow(env, surface);
368feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (env->ExceptionCheck()) {
3693c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk            return NULL;
370feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
371feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    } else {
372feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowNullPointerException(env, "surface");
3733c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
374feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
375feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (anw == NULL) {
376feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
377feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                "Surface had no valid native window.");
3783c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
379feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
380feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return anw;
381feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
382feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
38328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic sp<ANativeWindow> getNativeWindowFromTexture(JNIEnv* env, jobject surfaceTexture) {
38428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
38528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (surfaceTexture) {
38628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        anw = android_SurfaceTexture_getNativeWindow(env, surfaceTexture);
38728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        if (env->ExceptionCheck()) {
38828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk            return NULL;
38928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        }
39028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    } else {
39128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jniThrowNullPointerException(env, "surfaceTexture");
39228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return NULL;
39328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
39428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (anw == NULL) {
39528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
39628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                "SurfaceTexture had no valid native window.");
39728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return NULL;
39828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
39928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return anw;
40028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
40128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
4023c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkstatic sp<Surface> getSurface(JNIEnv* env, jobject surface) {
4033c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<Surface> s;
4043c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (surface) {
4053c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        s = android_view_Surface_getSurface(env, surface);
4063c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        if (env->ExceptionCheck()) {
4073c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk            return NULL;
4083c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        }
4093c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    } else {
4103c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        jniThrowNullPointerException(env, "surface");
4113c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
4123c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
4133c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (s == NULL) {
4143c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
4153c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk                "Surface had no valid native Surface.");
4163c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
4173c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
4183c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    return s;
4193c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk}
4203c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
421feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkextern "C" {
422feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
423feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) {
424feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeDetectSurfaceType");
425feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
426feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
427feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
428ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
429feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
430feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int32_t fmt = 0;
431feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt);
432feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if(err != NO_ERROR) {
433ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err),
434ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                err);
435ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
436feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
437feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return fmt;
438feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
439feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
440ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz,
441feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk          jobject surface, jintArray dimens) {
442feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeGetSurfaceDimens");
44328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
44428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (dimens == NULL) {
44528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Null dimens argument passed to nativeDetectSurfaceDimens", __FUNCTION__);
44628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
44728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
44828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
44928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (env->GetArrayLength(dimens) < 2) {
45028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Invalid length of dimens argument in nativeDetectSurfaceDimens", __FUNCTION__);
45128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
45228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
45328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
454feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
455feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
456feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
457ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
458feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
459feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int32_t dimenBuf[2];
460feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
461feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if(err != NO_ERROR) {
462ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err),
463ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                err);
464ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
465feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
466feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
467feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if(err != NO_ERROR) {
468ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while querying surface height %s (%d).", __FUNCTION__, strerror(-err),
469ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                err);
470ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
471feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
472feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
473ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
474feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
475feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
476f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunkstatic jint LegacyCameraDevice_nativeDetectSurfaceUsageFlags(JNIEnv* env, jobject thiz,
477f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk          jobject surface) {
478f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    ALOGV("nativeDetectSurfaceUsageFlags");
479f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk
480f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    sp<ANativeWindow> anw;
481f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
482f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        jniThrowException(env, "Ljava/lang/UnsupportedOperationException;",
483f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk            "Could not retrieve native window from surface.");
484f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        return BAD_VALUE;
485f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    }
486f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    int32_t usage = 0;
487f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
488f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    if(err != NO_ERROR) {
489f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        jniThrowException(env, "Ljava/lang/UnsupportedOperationException;",
490f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk            "Error while querying surface usage bits");
491f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        return err;
492f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    }
493f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    return usage;
494f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk}
495f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk
49628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz,
49728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jobject surfaceTexture, jintArray dimens) {
49828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("nativeDetectTextureDimens");
49928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
50028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if ((anw = getNativeWindowFromTexture(env, surfaceTexture)) == NULL) {
50128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Could not retrieve native window from SurfaceTexture.", __FUNCTION__);
50228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
50328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
50428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
50528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t dimenBuf[2];
50628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
50728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if(err != NO_ERROR) {
50828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Error while querying SurfaceTexture width %s (%d)", __FUNCTION__,
50928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
51028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
51128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
51228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
51328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
51428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if(err != NO_ERROR) {
51528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Error while querying SurfaceTexture height %s (%d)", __FUNCTION__,
51628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
51728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
51828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
51928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
52028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
52128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (env->ExceptionCheck()) {
52228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
52328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
52428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return NO_ERROR;
52528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
52628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
527ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface,
528feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint width, jint height, jint pixelFormat) {
529feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeConfigureSurface");
530feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
531feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
532feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
533ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
534feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
535feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK);
536feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
537ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
538ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
539feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
540ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
541feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
542feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
543ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface,
544feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) {
545feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeProduceFrame");
546feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
547feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
548feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
549feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
550ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
551feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
552feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
553feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (pixelBuffer == NULL) {
554feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowNullPointerException(env, "pixelBuffer");
555ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return DONT_CARE;
556feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
557feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
558feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer));
559feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL);
560feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
561feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (pixels == NULL) {
562feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowNullPointerException(env, "pixels");
563ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return DONT_CARE;
564feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
565feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
566feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height,
567feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            pixelFormat, bufSize);
568feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT);
569feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
570feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
571ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err);
572ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
573feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
574ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
575feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
576feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
577ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface,
578feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint pixelFormat) {
579feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeSetSurfaceType");
580feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
581feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
582feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
583ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
584feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
585feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = native_window_set_buffers_format(anw.get(), pixelFormat);
586feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
587ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err);
588ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
589feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
590ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
591feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
592feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
593ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface,
594feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint width, jint height) {
595feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeSetSurfaceDimens");
596feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
597feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
598feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
599ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
600feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
601feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = native_window_set_buffers_dimensions(anw.get(), width, height);
602feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
603ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while setting surface dimens %s (%d).", __FUNCTION__, strerror(-err), err);
604ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
605feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
606a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk
607a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    // WAR - Set user dimensions also to avoid incorrect scaling after TextureView orientation
608a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    // change.
609a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    err = native_window_set_buffers_user_dimensions(anw.get(), width, height);
610a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    if (err != NO_ERROR) {
611a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk        ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err),
612a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk                err);
613a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk        return err;
614a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    }
615ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
616feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
617feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
6183c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkstatic jlong LegacyCameraDevice_nativeGetSurfaceId(JNIEnv* env, jobject thiz, jobject surface) {
6193c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    ALOGV("nativeGetSurfaceId");
6203c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<Surface> s;
6213c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if ((s = getSurface(env, surface)) == NULL) {
6223c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve native Surface from surface.", __FUNCTION__);
6233c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6243c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6253c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<IGraphicBufferProducer> gbp = s->getIGraphicBufferProducer();
6263c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (gbp == NULL) {
6273c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve IGraphicBufferProducer from surface.", __FUNCTION__);
6283c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6293c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
63097069dd4fd5454ba057ccf2854d7f925c337884cMarco Nelissen    sp<IBinder> b = IInterface::asBinder(gbp);
6313c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (b == NULL) {
6323c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve IBinder from surface.", __FUNCTION__);
6333c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6343c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6353c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    /*
6363c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     * FIXME: Use better unique ID for surfaces than native IBinder pointer.  Fix also in the camera
6373c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     * service (CameraDeviceClient.h).
6383c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     */
6393c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    return reinterpret_cast<jlong>(b.get());
6403c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk}
6413c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
64228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv* env, jobject thiz,
64328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jobject surface, jint facing, jint orientation) {
64428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("nativeSetSurfaceOrientation");
64528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
64628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
64728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
64828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
64928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
65028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
65128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    status_t err = NO_ERROR;
65228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    CameraMetadata staticMetadata;
65328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
65428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t orientVal = static_cast<int32_t>(orientation);
65528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    uint8_t facingVal = static_cast<uint8_t>(facing);
65628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1);
65728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1);
65828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
65928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t transform = 0;
66028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
66191838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) {
66228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Invalid rotation transform %s (%d)", __FUNCTION__, strerror(-err),
66328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                err);
66428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
66528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
66628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
66728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("%s: Setting buffer sticky transform to %d", __FUNCTION__, transform);
66828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
66991838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) {
67028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Unable to configure surface transform, error %s (%d)", __FUNCTION__,
67128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
67228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
67328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
67428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
67528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return NO_ERROR;
67628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
67728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
67891838ded36131525312739c0929913b215519c2aRuben Brunkstatic jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz, jobject surface,
67991838ded36131525312739c0929913b215519c2aRuben Brunk        jlong timestamp) {
68091838ded36131525312739c0929913b215519c2aRuben Brunk    ALOGV("nativeSetNextTimestamp");
68191838ded36131525312739c0929913b215519c2aRuben Brunk    sp<ANativeWindow> anw;
68291838ded36131525312739c0929913b215519c2aRuben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
68391838ded36131525312739c0929913b215519c2aRuben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
68491838ded36131525312739c0929913b215519c2aRuben Brunk        return BAD_VALUE;
68591838ded36131525312739c0929913b215519c2aRuben Brunk    }
68691838ded36131525312739c0929913b215519c2aRuben Brunk
68791838ded36131525312739c0929913b215519c2aRuben Brunk    status_t err = NO_ERROR;
68891838ded36131525312739c0929913b215519c2aRuben Brunk
68991838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = native_window_set_buffers_timestamp(anw.get(), static_cast<int64_t>(timestamp))) !=
69091838ded36131525312739c0929913b215519c2aRuben Brunk            NO_ERROR) {
69191838ded36131525312739c0929913b215519c2aRuben Brunk        ALOGE("%s: Unable to set surface timestamp, error %s (%d)", __FUNCTION__, strerror(-err),
69291838ded36131525312739c0929913b215519c2aRuben Brunk                err);
69391838ded36131525312739c0929913b215519c2aRuben Brunk        return err;
69491838ded36131525312739c0929913b215519c2aRuben Brunk    }
69591838ded36131525312739c0929913b215519c2aRuben Brunk    return NO_ERROR;
69691838ded36131525312739c0929913b215519c2aRuben Brunk}
69791838ded36131525312739c0929913b215519c2aRuben Brunk
6981dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunkstatic jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) {
6991dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    ALOGV("nativeGetJpegFooterSize");
7001dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    return static_cast<jint>(sizeof(struct camera3_jpeg_blob));
7011dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk}
7021dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk
703feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk} // extern "C"
704feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
705feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic JNINativeMethod gCameraDeviceMethods[] = {
706feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeDetectSurfaceType",
707feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    "(Landroid/view/Surface;)I",
708feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectSurfaceType },
709feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeDetectSurfaceDimens",
710ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;[I)I",
711feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
712feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeConfigureSurface",
713ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;III)I",
714feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeConfigureSurface },
715feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeProduceFrame",
716ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;[BIII)I",
717feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeProduceFrame },
718feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeSetSurfaceFormat",
719ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;I)I",
720feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceFormat },
721feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeSetSurfaceDimens",
722ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;II)I",
723feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceDimens },
7243c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    { "nativeGetSurfaceId",
7253c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    "(Landroid/view/Surface;)J",
7263c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    (void *)LegacyCameraDevice_nativeGetSurfaceId },
72728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    { "nativeDetectTextureDimens",
72828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    "(Landroid/graphics/SurfaceTexture;[I)I",
72928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectTextureDimens },
73028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    { "nativeSetSurfaceOrientation",
73128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    "(Landroid/view/Surface;II)I",
73228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceOrientation },
73391838ded36131525312739c0929913b215519c2aRuben Brunk    { "nativeSetNextTimestamp",
73491838ded36131525312739c0929913b215519c2aRuben Brunk    "(Landroid/view/Surface;J)I",
73591838ded36131525312739c0929913b215519c2aRuben Brunk    (void *)LegacyCameraDevice_nativeSetNextTimestamp },
7361dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    { "nativeGetJpegFooterSize",
7371dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    "()I",
7381dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    (void *)LegacyCameraDevice_nativeGetJpegFooterSize },
739f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    { "nativeDetectSurfaceUsageFlags",
740f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    "(Landroid/view/Surface;)I",
741f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectSurfaceUsageFlags },
742feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk};
743feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
744feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk// Get all the required offsets in java class and register native functions
745feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkint register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env)
746feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk{
747feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // Register native functions
748ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return RegisterMethodsOrDie(env,
749feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            CAMERA_DEVICE_CLASS_NAME,
750feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            gCameraDeviceMethods,
751feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            NELEM(gCameraDeviceMethods));
752feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
753feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
754