android_hardware_camera2_legacy_LegacyCameraDevice.cpp revision 31798f33184fd59dd3d3cc55e6373d9f91d220b6
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"
26feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include "android_runtime/AndroidRuntime.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/**
52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Convert from RGB 888 to Y'CbCr using the conversion specified in ITU-R BT.601 for
53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * digital RGB with K_b = 0.114, and K_r = 0.299.
54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
5531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunkstatic void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane,
56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        uint8_t* uPlane, uint8_t* vPlane, size_t chromaStep, size_t yStride, size_t chromaStride) {
57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    uint8_t R, G, B;
58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    size_t index = 0;
59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
6031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t cStrideDiff = chromaStride - width;
61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
6231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    for (size_t j = 0; j < height; j++) {
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++];
67feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            *(yPlane + i) = ((66 * R + 129 * G +  25 * B + 128) >> 8) +  16;
68feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
69feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (j % 2 == 0 && i % 2 == 0){
70feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                *uPlane = (( -38 * R -  74 * G + 112 * B + 128) >> 8) + 128;
71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                *vPlane = (( 112 * R -  94 * G -  18 * B + 128) >> 8) + 128;
72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                uPlane += chromaStep;
73feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                vPlane += chromaStep;
74feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // Skip alpha
76feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            index++;
77feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
78feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        yPlane += yStride;
79feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (j % 2 == 0) {
80feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uPlane += cStrideDiff;
81feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            vPlane += cStrideDiff;
82feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
83feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
84feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
85feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
8631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunkstatic void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, android_ycbcr* ycbcr) {
87feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    size_t cStep = ycbcr->chroma_step;
88feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    size_t cStride = ycbcr->cstride;
89feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    size_t yStride = ycbcr->ystride;
90feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    rgbToYuv420(rgbBuf, width, height, reinterpret_cast<uint8_t*>(ycbcr->y),
91feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            reinterpret_cast<uint8_t*>(ycbcr->cb), reinterpret_cast<uint8_t*>(ycbcr->cr),
92feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            cStep, yStride, cStride);
93feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
94feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
95feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic status_t configureSurface(const sp<ANativeWindow>& anw,
96feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 int32_t width,
97feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 int32_t height,
98feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 int32_t pixelFmt,
99feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 int32_t maxBufferSlack) {
100feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = NO_ERROR;
101feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_set_buffers_dimensions(anw.get(), width, height);
102feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
103feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window buffer dimensions, error %s (%d).", __FUNCTION__,
104feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
105feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
106feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
107feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
108feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_set_buffers_format(anw.get(), pixelFmt);
109feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
110feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window buffer format, error %s (%d).", __FUNCTION__,
111feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
112feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
113feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
114feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
115feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
116feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
117feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__,
118feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
119feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
120feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
121feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
122feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int minUndequeuedBuffers;
123feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = anw.get()->query(anw.get(),
124feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
125feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            &minUndequeuedBuffers);
126feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
127feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).",
128feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                __FUNCTION__, strerror(-err), err);
129feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
130feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
131feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
1325096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    ALOGV("%s: Setting buffer count to %d, size to (%dx%d), fmt (0x%x)", __FUNCTION__,
1335096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin          maxBufferSlack + 1 + minUndequeuedBuffers,
1345096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin          width, height, pixelFmt);
135feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_set_buffer_count(anw.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
136feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
137feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
138feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
139feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
140feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
141feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return NO_ERROR;
142feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
143feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
144feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
145feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Produce a frame in the given surface.
146feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
147feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Args:
148feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    anw - a surface to produce a frame in.
149feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    pixelBuffer - image buffer to generate a frame from.
150feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    width - width of the pixelBuffer in pixels.
151feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    height - height of the pixelBuffer in pixels.
152feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    pixelFmt - format of the pixelBuffer, one of:
153feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *               HAL_PIXEL_FORMAT_YCrCb_420_SP,
154feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *               HAL_PIXEL_FORMAT_YCbCr_420_888,
155feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *               HAL_PIXEL_FORMAT_BLOB
156feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    bufSize - the size of the pixelBuffer in bytes.
157feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
158feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic status_t produceFrame(const sp<ANativeWindow>& anw,
159feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                             uint8_t* pixelBuffer,
16031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                             int32_t bufWidth, // Width of the pixelBuffer
16131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                             int32_t bufHeight, // Height of the pixelBuffer
162feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                             int32_t pixelFmt, // Format of the pixelBuffer
1635096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin                             int32_t bufSize) {
164feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ATRACE_CALL();
165feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = NO_ERROR;
166feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ANativeWindowBuffer* anb;
1675096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
16831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            __FUNCTION__, anw.get(), bufWidth, bufHeight, pixelFmt, bufSize);
1695096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin
1705096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    if (anw == 0) {
1715096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: anw must not be NULL", __FUNCTION__);
1725096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
1735096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    } else if (pixelBuffer == NULL) {
1745096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__);
1755096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
17631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    } else if (bufWidth < 0) {
1775096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: width must be non-negative", __FUNCTION__);
1785096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
17931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    } else if (bufHeight < 0) {
1805096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: height must be non-negative", __FUNCTION__);
1815096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
1825096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    } else if (bufSize < 0) {
1835096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: bufSize must be non-negative", __FUNCTION__);
1845096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
1855096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    }
186feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
18731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t width = static_cast<size_t>(bufWidth);
18831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t height = static_cast<size_t>(bufHeight);
18931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t bufferLength = static_cast<size_t>(bufSize);
19091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
191feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // TODO: Switch to using Surface::lock and Surface::unlockAndPost
192feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
193feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) return err;
194feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
195feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));
19631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    uint32_t gBufWidth = buf->getWidth();
19731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    uint32_t gBufHeight = buf->getHeight();
19831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    if (gBufWidth != width || gBufHeight != height) {
19931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32
20031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ", expecting dimensions %zu x %zu",  __FUNCTION__, gBufWidth, gBufHeight,
20131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                width, height);
20231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        return BAD_VALUE;
20331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
20431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
20531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    int32_t bufFmt = 0;
20631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &bufFmt);
20731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    if (err != NO_ERROR) {
20831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__,
20931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                strerror(-err), err);
21031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        return err;
21131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
21231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
21331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    uint64_t tmpSize = width * height;
21431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    if (bufFmt != pixelFmt) {
21531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        if (bufFmt == HAL_PIXEL_FORMAT_RGBA_8888 && pixelFmt == HAL_PIXEL_FORMAT_BLOB) {
21631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            ALOGV("%s: Using BLOB to RGBA format override.", __FUNCTION__);
21731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            tmpSize *= 4;
21831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        } else {
21931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            ALOGW("%s: Format mismatch in produceFrame: expecting format %#" PRIx32
22031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                    ", but received buffer with format %#" PRIx32, __FUNCTION__, pixelFmt, bufFmt);
22131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        }
22231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
22331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
22431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    if (tmpSize > SIZE_MAX) {
22531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        ALOGE("%s: Overflow calculating size, buffer with dimens %zu x %zu is absurdly large...",
22631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                __FUNCTION__, width, height);
22731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        return BAD_VALUE;
22831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
22931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
23031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t totalSizeBytes = tmpSize;
231feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
232feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    switch(pixelFmt) {
233feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
23431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (bufferLength < totalSizeBytes) {
23531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
23631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, bufferLength);
237feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return BAD_VALUE;
238feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
239feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* img = NULL;
240feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
241feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
242feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (err != NO_ERROR) return err;
243feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
244feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* yPlane = img;
245feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* uPlane = img + height * width;
246feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* vPlane = uPlane + 1;
247feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            size_t chromaStep = 2;
248feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            size_t yStride = width;
249feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            size_t chromaStride = width;
250feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
251feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            rgbToYuv420(pixelBuffer, width, height, yPlane,
252feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    uPlane, vPlane, chromaStep, yStride, chromaStride);
253feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            break;
254feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
25591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk        case HAL_PIXEL_FORMAT_YV12: {
25631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (bufferLength < totalSizeBytes) {
25731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
25831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, bufferLength);
25991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                return BAD_VALUE;
26091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            }
26191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
26291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            if ((width & 1) || (height & 1)) {
26331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height);
26491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                return BAD_VALUE;
26591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            }
26691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
26791b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* img = NULL;
26891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
26991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
27091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            if (err != NO_ERROR) {
27191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                ALOGE("%s: Error %s (%d) while locking gralloc buffer for write.", __FUNCTION__,
27291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                        strerror(-err), err);
27391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                return err;
27491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            }
27591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
27691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint32_t stride = buf->getStride();
27791b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            LOG_ALWAYS_FATAL_IF(stride % 16, "Stride is not 16 pixel aligned %d", stride);
27891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
27991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint32_t cStride = ALIGN(stride / 2, 16);
28091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            size_t chromaStep = 1;
28191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
28291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* yPlane = img;
28391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* crPlane = img + static_cast<uint32_t>(height) * stride;
28491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* cbPlane = crPlane + cStride * static_cast<uint32_t>(height) / 2;
28591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
28691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            rgbToYuv420(pixelBuffer, width, height, yPlane,
28791b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                    crPlane, cbPlane, chromaStep, stride, cStride);
28891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            break;
28991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk        }
290feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        case HAL_PIXEL_FORMAT_YCbCr_420_888: {
291feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // Software writes with YCbCr_420_888 format are unsupported
292feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // by the gralloc module for now
29331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (bufferLength < totalSizeBytes) {
29431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
29531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, bufferLength);
296feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return BAD_VALUE;
297feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
298feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            android_ycbcr ycbcr = android_ycbcr();
299feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
300feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
301feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            err = buf->lockYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr);
302feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (err != NO_ERROR) {
303feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                ALOGE("%s: Failed to lock ycbcr buffer, error %s (%d).", __FUNCTION__,
304feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        strerror(-err), err);
305feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return err;
306feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
307feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            rgbToYuv420(pixelBuffer, width, height, &ycbcr);
308feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            break;
309feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
310feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        case HAL_PIXEL_FORMAT_BLOB: {
311feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int8_t* img = NULL;
3120fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk            struct camera3_jpeg_blob footer = {
3130fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk                jpeg_blob_id: CAMERA3_JPEG_BLOB_ID,
3140fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk                jpeg_size: (uint32_t)width
3150fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk            };
3160fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk
31731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            size_t totalJpegSize = bufferLength + sizeof(footer);
31831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble
31931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
32031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (height != 1) {
32131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: Invalid height set for JPEG buffer output, %zu", __FUNCTION__, height);
32231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                return BAD_VALUE;
32331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            }
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
47628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz,
47728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jobject surfaceTexture, jintArray dimens) {
47828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("nativeDetectTextureDimens");
47928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
48028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if ((anw = getNativeWindowFromTexture(env, surfaceTexture)) == NULL) {
48128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Could not retrieve native window from SurfaceTexture.", __FUNCTION__);
48228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
48328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
48428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
48528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t dimenBuf[2];
48628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
48728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if(err != NO_ERROR) {
48828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Error while querying SurfaceTexture width %s (%d)", __FUNCTION__,
48928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
49028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
49128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
49228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
49328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
49428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if(err != NO_ERROR) {
49528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Error while querying SurfaceTexture height %s (%d)", __FUNCTION__,
49628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
49728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
49828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
49928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
50028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
50128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (env->ExceptionCheck()) {
50228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
50328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
50428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return NO_ERROR;
50528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
50628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
507ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface,
508feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint width, jint height, jint pixelFormat) {
509feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeConfigureSurface");
510feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
511feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
512feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
513ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
514feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
515feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK);
516feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
517ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
518ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
519feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
520ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
521feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
522feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
523ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface,
524feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) {
525feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeProduceFrame");
526feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
527feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
528feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
529feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
530ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
531feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
532feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
533feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (pixelBuffer == NULL) {
534feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowNullPointerException(env, "pixelBuffer");
535ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return DONT_CARE;
536feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
537feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
538feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer));
539feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL);
540feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
541feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (pixels == NULL) {
542feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowNullPointerException(env, "pixels");
543ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return DONT_CARE;
544feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
545feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
546feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height,
547feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            pixelFormat, bufSize);
548feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT);
549feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
550feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
551ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err);
552ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
553feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
554ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
555feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
556feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
557ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface,
558feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint pixelFormat) {
559feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeSetSurfaceType");
560feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
561feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
562feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
563ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
564feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
565feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = native_window_set_buffers_format(anw.get(), pixelFormat);
566feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
567ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err);
568ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
569feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
570ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
571feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
572feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
573ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface,
574feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint width, jint height) {
575feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeSetSurfaceDimens");
576feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
577feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
578feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
579ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
580feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
581feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = native_window_set_buffers_dimensions(anw.get(), width, height);
582feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
583ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while setting surface dimens %s (%d).", __FUNCTION__, strerror(-err), err);
584ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
585feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
586a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk
587a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    // WAR - Set user dimensions also to avoid incorrect scaling after TextureView orientation
588a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    // change.
589a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    err = native_window_set_buffers_user_dimensions(anw.get(), width, height);
590a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    if (err != NO_ERROR) {
591a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk        ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err),
592a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk                err);
593a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk        return err;
594a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    }
595ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
596feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
597feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
5983c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkstatic jlong LegacyCameraDevice_nativeGetSurfaceId(JNIEnv* env, jobject thiz, jobject surface) {
5993c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    ALOGV("nativeGetSurfaceId");
6003c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<Surface> s;
6013c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if ((s = getSurface(env, surface)) == NULL) {
6023c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve native Surface from surface.", __FUNCTION__);
6033c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6043c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6053c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<IGraphicBufferProducer> gbp = s->getIGraphicBufferProducer();
6063c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (gbp == NULL) {
6073c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve IGraphicBufferProducer from surface.", __FUNCTION__);
6083c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6093c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6103c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<IBinder> b = gbp->asBinder();
6113c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (b == NULL) {
6123c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve IBinder from surface.", __FUNCTION__);
6133c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6143c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6153c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    /*
6163c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     * FIXME: Use better unique ID for surfaces than native IBinder pointer.  Fix also in the camera
6173c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     * service (CameraDeviceClient.h).
6183c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     */
6193c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    return reinterpret_cast<jlong>(b.get());
6203c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk}
6213c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
62228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv* env, jobject thiz,
62328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jobject surface, jint facing, jint orientation) {
62428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("nativeSetSurfaceOrientation");
62528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
62628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
62728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
62828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
62928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
63028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
63128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    status_t err = NO_ERROR;
63228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    CameraMetadata staticMetadata;
63328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
63428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t orientVal = static_cast<int32_t>(orientation);
63528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    uint8_t facingVal = static_cast<uint8_t>(facing);
63628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1);
63728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1);
63828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
63928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t transform = 0;
64028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
64191838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) {
64228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Invalid rotation transform %s (%d)", __FUNCTION__, strerror(-err),
64328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                err);
64428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
64528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
64628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
64728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("%s: Setting buffer sticky transform to %d", __FUNCTION__, transform);
64828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
64991838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) {
65028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Unable to configure surface transform, error %s (%d)", __FUNCTION__,
65128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
65228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
65328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
65428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
65528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return NO_ERROR;
65628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
65728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
65891838ded36131525312739c0929913b215519c2aRuben Brunkstatic jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz, jobject surface,
65991838ded36131525312739c0929913b215519c2aRuben Brunk        jlong timestamp) {
66091838ded36131525312739c0929913b215519c2aRuben Brunk    ALOGV("nativeSetNextTimestamp");
66191838ded36131525312739c0929913b215519c2aRuben Brunk    sp<ANativeWindow> anw;
66291838ded36131525312739c0929913b215519c2aRuben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
66391838ded36131525312739c0929913b215519c2aRuben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
66491838ded36131525312739c0929913b215519c2aRuben Brunk        return BAD_VALUE;
66591838ded36131525312739c0929913b215519c2aRuben Brunk    }
66691838ded36131525312739c0929913b215519c2aRuben Brunk
66791838ded36131525312739c0929913b215519c2aRuben Brunk    status_t err = NO_ERROR;
66891838ded36131525312739c0929913b215519c2aRuben Brunk
66991838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = native_window_set_buffers_timestamp(anw.get(), static_cast<int64_t>(timestamp))) !=
67091838ded36131525312739c0929913b215519c2aRuben Brunk            NO_ERROR) {
67191838ded36131525312739c0929913b215519c2aRuben Brunk        ALOGE("%s: Unable to set surface timestamp, error %s (%d)", __FUNCTION__, strerror(-err),
67291838ded36131525312739c0929913b215519c2aRuben Brunk                err);
67391838ded36131525312739c0929913b215519c2aRuben Brunk        return err;
67491838ded36131525312739c0929913b215519c2aRuben Brunk    }
67591838ded36131525312739c0929913b215519c2aRuben Brunk    return NO_ERROR;
67691838ded36131525312739c0929913b215519c2aRuben Brunk}
67791838ded36131525312739c0929913b215519c2aRuben Brunk
6781dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunkstatic jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) {
6791dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    ALOGV("nativeGetJpegFooterSize");
6801dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    return static_cast<jint>(sizeof(struct camera3_jpeg_blob));
6811dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk}
6821dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk
683feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk} // extern "C"
684feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
685feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic JNINativeMethod gCameraDeviceMethods[] = {
686feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeDetectSurfaceType",
687feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    "(Landroid/view/Surface;)I",
688feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectSurfaceType },
689feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeDetectSurfaceDimens",
690ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;[I)I",
691feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
692feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeConfigureSurface",
693ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;III)I",
694feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeConfigureSurface },
695feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeProduceFrame",
696ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;[BIII)I",
697feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeProduceFrame },
698feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeSetSurfaceFormat",
699ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;I)I",
700feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceFormat },
701feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeSetSurfaceDimens",
702ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;II)I",
703feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceDimens },
7043c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    { "nativeGetSurfaceId",
7053c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    "(Landroid/view/Surface;)J",
7063c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    (void *)LegacyCameraDevice_nativeGetSurfaceId },
70728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    { "nativeDetectTextureDimens",
70828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    "(Landroid/graphics/SurfaceTexture;[I)I",
70928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectTextureDimens },
71028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    { "nativeSetSurfaceOrientation",
71128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    "(Landroid/view/Surface;II)I",
71228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceOrientation },
71391838ded36131525312739c0929913b215519c2aRuben Brunk    { "nativeSetNextTimestamp",
71491838ded36131525312739c0929913b215519c2aRuben Brunk    "(Landroid/view/Surface;J)I",
71591838ded36131525312739c0929913b215519c2aRuben Brunk    (void *)LegacyCameraDevice_nativeSetNextTimestamp },
7161dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    { "nativeGetJpegFooterSize",
7171dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    "()I",
7181dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    (void *)LegacyCameraDevice_nativeGetJpegFooterSize },
719feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk};
720feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
721feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk// Get all the required offsets in java class and register native functions
722feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkint register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env)
723feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk{
724feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // Register native functions
725feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return AndroidRuntime::registerNativeMethods(env,
726feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            CAMERA_DEVICE_CLASS_NAME,
727feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            gCameraDeviceMethods,
728feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            NELEM(gCameraDeviceMethods));
729feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
730feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
731