android_hardware_camera2_legacy_LegacyCameraDevice.cpp revision 443ab2c7dbe2a3a482892f3171882572f10eab9a
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/**
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,
55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        uint8_t* uPlane, uint8_t* vPlane, 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++) {
59433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk        uint8_t* u = uPlane;
60433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk        uint8_t* v = vPlane;
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) {
69433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk                *v = (( -43 * R - 85 * G + 128 * B) >> 8) + 128;
70433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk                *u = (( 128 * R - 107 * G - 21 * B) >> 8) + 128;
71433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk                u += chromaStep;
72433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk                v += chromaStep;
73feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
74feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // Skip alpha
75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            index++;
76feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
77feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        yPlane += yStride;
78433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk        if (jEven) {
79433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk            uPlane += chromaStride;
80433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk            vPlane += 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 = {
3180fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk                jpeg_blob_id: CAMERA3_JPEG_BLOB_ID,
3190c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk                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) {
376443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk        ALOGE("%s: Surface had no valid native window.", __FUNCTION__);
3773c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
378feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
379feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return anw;
380feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
381feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
38228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic sp<ANativeWindow> getNativeWindowFromTexture(JNIEnv* env, jobject surfaceTexture) {
38328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
38428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (surfaceTexture) {
38528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        anw = android_SurfaceTexture_getNativeWindow(env, surfaceTexture);
38628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        if (env->ExceptionCheck()) {
38728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk            return NULL;
38828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        }
38928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    } else {
39028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jniThrowNullPointerException(env, "surfaceTexture");
39128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return NULL;
39228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
39328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (anw == NULL) {
39428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
39528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                "SurfaceTexture had no valid native window.");
39628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return NULL;
39728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
39828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return anw;
39928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
40028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
4013c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkstatic sp<Surface> getSurface(JNIEnv* env, jobject surface) {
4023c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<Surface> s;
4033c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (surface) {
4043c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        s = android_view_Surface_getSurface(env, surface);
4053c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        if (env->ExceptionCheck()) {
4063c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk            return NULL;
4073c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        }
4083c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    } else {
4093c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        jniThrowNullPointerException(env, "surface");
4103c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
4113c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
4123c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (s == NULL) {
4133c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
4143c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk                "Surface had no valid native Surface.");
4153c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
4163c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
4173c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    return s;
4183c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk}
4193c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
420feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkextern "C" {
421feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
422feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) {
423feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeDetectSurfaceType");
424feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
425feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
426feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
427ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
428feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
429feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int32_t fmt = 0;
430feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt);
431feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if(err != NO_ERROR) {
432ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err),
433ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                err);
434ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
435feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
436feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return fmt;
437feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
438feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
439ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz,
440feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk          jobject surface, jintArray dimens) {
441feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeGetSurfaceDimens");
44228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
44328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (dimens == NULL) {
44428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Null dimens argument passed to nativeDetectSurfaceDimens", __FUNCTION__);
44528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
44628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
44728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
44828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (env->GetArrayLength(dimens) < 2) {
44928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Invalid length of dimens argument in nativeDetectSurfaceDimens", __FUNCTION__);
45028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
45128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
45228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
453feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
454feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
455feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
456ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
457feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
458feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int32_t dimenBuf[2];
459feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
460feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if(err != NO_ERROR) {
461ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err),
462ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                err);
463ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
464feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
465feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
466feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if(err != NO_ERROR) {
467ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while querying surface height %s (%d).", __FUNCTION__, strerror(-err),
468ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                err);
469ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
470feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
471feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
472ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
473feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
474feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
475f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunkstatic jint LegacyCameraDevice_nativeDetectSurfaceUsageFlags(JNIEnv* env, jobject thiz,
476f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk          jobject surface) {
477f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    ALOGV("nativeDetectSurfaceUsageFlags");
478f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk
479f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    sp<ANativeWindow> anw;
480f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
481f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        jniThrowException(env, "Ljava/lang/UnsupportedOperationException;",
482f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk            "Could not retrieve native window from surface.");
483f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        return BAD_VALUE;
484f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    }
485f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    int32_t usage = 0;
486f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
487f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    if(err != NO_ERROR) {
488f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        jniThrowException(env, "Ljava/lang/UnsupportedOperationException;",
489f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk            "Error while querying surface usage bits");
490f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        return err;
491f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    }
492f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    return usage;
493f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk}
494f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk
49528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz,
49628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jobject surfaceTexture, jintArray dimens) {
49728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("nativeDetectTextureDimens");
49828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
49928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if ((anw = getNativeWindowFromTexture(env, surfaceTexture)) == NULL) {
50028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Could not retrieve native window from SurfaceTexture.", __FUNCTION__);
50128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
50228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
50328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
50428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t dimenBuf[2];
50528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
50628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if(err != NO_ERROR) {
50728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Error while querying SurfaceTexture width %s (%d)", __FUNCTION__,
50828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
50928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
51028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
51128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
51228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
51328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if(err != NO_ERROR) {
51428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Error while querying SurfaceTexture height %s (%d)", __FUNCTION__,
51528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
51628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
51728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
51828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
51928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
52028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (env->ExceptionCheck()) {
52128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
52228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
52328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return NO_ERROR;
52428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
52528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
526ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface,
527feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint width, jint height, jint pixelFormat) {
528feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeConfigureSurface");
529feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
530feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
531feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
532ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
533feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
534feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK);
535feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
536ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
537ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
538feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
539ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
540feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
541feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
542ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface,
543feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) {
544feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeProduceFrame");
545feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
546feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
547feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
548feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
549ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
550feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
551feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
552feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (pixelBuffer == NULL) {
553feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowNullPointerException(env, "pixelBuffer");
554ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return DONT_CARE;
555feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
556feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
557feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer));
558feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL);
559feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
560feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (pixels == NULL) {
561feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowNullPointerException(env, "pixels");
562ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return DONT_CARE;
563feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
564feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
565feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height,
566feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            pixelFormat, bufSize);
567feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT);
568feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
569feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
570ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err);
571ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
572feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
573ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
574feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
575feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
576ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface,
577feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint pixelFormat) {
578feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeSetSurfaceType");
579feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
580feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
581feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
582ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
583feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
584feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = native_window_set_buffers_format(anw.get(), pixelFormat);
585feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
586ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err);
587ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
588feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
589ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
590feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
591feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
592ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface,
593feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint width, jint height) {
594feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeSetSurfaceDimens");
595feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
596feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
597feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
598ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
599feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
600a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk
601b0acf7fcfab08b5af1f99daa51bedbb659d18926Eino-Ville Talvala    // Set user dimensions only
602b0acf7fcfab08b5af1f99daa51bedbb659d18926Eino-Ville Talvala    // The producer dimensions are owned by GL
603b0acf7fcfab08b5af1f99daa51bedbb659d18926Eino-Ville Talvala    status_t err = native_window_set_buffers_user_dimensions(anw.get(), width, height);
604a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    if (err != NO_ERROR) {
605a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk        ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err),
606a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk                err);
607a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk        return err;
608a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    }
609ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
610feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
611feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
6123c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkstatic jlong LegacyCameraDevice_nativeGetSurfaceId(JNIEnv* env, jobject thiz, jobject surface) {
6133c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    ALOGV("nativeGetSurfaceId");
6143c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<Surface> s;
6153c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if ((s = getSurface(env, surface)) == NULL) {
6163c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve native Surface from surface.", __FUNCTION__);
6173c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6183c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6193c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<IGraphicBufferProducer> gbp = s->getIGraphicBufferProducer();
6203c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (gbp == NULL) {
6213c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve IGraphicBufferProducer from surface.", __FUNCTION__);
6223c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6233c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6243c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<IBinder> b = gbp->asBinder();
6253c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (b == NULL) {
6263c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve IBinder from surface.", __FUNCTION__);
6273c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6283c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6293c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    /*
6303c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     * FIXME: Use better unique ID for surfaces than native IBinder pointer.  Fix also in the camera
6313c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     * service (CameraDeviceClient.h).
6323c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     */
6333c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    return reinterpret_cast<jlong>(b.get());
6343c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk}
6353c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
63628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv* env, jobject thiz,
63728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jobject surface, jint facing, jint orientation) {
63828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("nativeSetSurfaceOrientation");
63928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
64028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
64128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
64228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
64328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
64428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
64528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    status_t err = NO_ERROR;
64628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    CameraMetadata staticMetadata;
64728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
64828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t orientVal = static_cast<int32_t>(orientation);
64928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    uint8_t facingVal = static_cast<uint8_t>(facing);
65028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1);
65128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1);
65228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
65328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t transform = 0;
65428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
65591838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) {
65628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Invalid rotation transform %s (%d)", __FUNCTION__, strerror(-err),
65728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                err);
65828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
65928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
66028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
66128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("%s: Setting buffer sticky transform to %d", __FUNCTION__, transform);
66228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
66391838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) {
66428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Unable to configure surface transform, error %s (%d)", __FUNCTION__,
66528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
66628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
66728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
66828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
66928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return NO_ERROR;
67028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
67128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
67291838ded36131525312739c0929913b215519c2aRuben Brunkstatic jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz, jobject surface,
67391838ded36131525312739c0929913b215519c2aRuben Brunk        jlong timestamp) {
67491838ded36131525312739c0929913b215519c2aRuben Brunk    ALOGV("nativeSetNextTimestamp");
67591838ded36131525312739c0929913b215519c2aRuben Brunk    sp<ANativeWindow> anw;
67691838ded36131525312739c0929913b215519c2aRuben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
67791838ded36131525312739c0929913b215519c2aRuben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
67891838ded36131525312739c0929913b215519c2aRuben Brunk        return BAD_VALUE;
67991838ded36131525312739c0929913b215519c2aRuben Brunk    }
68091838ded36131525312739c0929913b215519c2aRuben Brunk
68191838ded36131525312739c0929913b215519c2aRuben Brunk    status_t err = NO_ERROR;
68291838ded36131525312739c0929913b215519c2aRuben Brunk
68391838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = native_window_set_buffers_timestamp(anw.get(), static_cast<int64_t>(timestamp))) !=
68491838ded36131525312739c0929913b215519c2aRuben Brunk            NO_ERROR) {
68591838ded36131525312739c0929913b215519c2aRuben Brunk        ALOGE("%s: Unable to set surface timestamp, error %s (%d)", __FUNCTION__, strerror(-err),
68691838ded36131525312739c0929913b215519c2aRuben Brunk                err);
68791838ded36131525312739c0929913b215519c2aRuben Brunk        return err;
68891838ded36131525312739c0929913b215519c2aRuben Brunk    }
68991838ded36131525312739c0929913b215519c2aRuben Brunk    return NO_ERROR;
69091838ded36131525312739c0929913b215519c2aRuben Brunk}
69191838ded36131525312739c0929913b215519c2aRuben Brunk
6921dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunkstatic jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) {
6931dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    ALOGV("nativeGetJpegFooterSize");
6941dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    return static_cast<jint>(sizeof(struct camera3_jpeg_blob));
6951dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk}
6961dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk
697feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk} // extern "C"
698feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
699feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic JNINativeMethod gCameraDeviceMethods[] = {
700feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeDetectSurfaceType",
701feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    "(Landroid/view/Surface;)I",
702feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectSurfaceType },
703feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeDetectSurfaceDimens",
704ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;[I)I",
705feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
706feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeConfigureSurface",
707ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;III)I",
708feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeConfigureSurface },
709feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeProduceFrame",
710ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;[BIII)I",
711feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeProduceFrame },
712feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeSetSurfaceFormat",
713ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;I)I",
714feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceFormat },
715feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeSetSurfaceDimens",
716ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;II)I",
717feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceDimens },
7183c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    { "nativeGetSurfaceId",
7193c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    "(Landroid/view/Surface;)J",
7203c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    (void *)LegacyCameraDevice_nativeGetSurfaceId },
72128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    { "nativeDetectTextureDimens",
72228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    "(Landroid/graphics/SurfaceTexture;[I)I",
72328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectTextureDimens },
72428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    { "nativeSetSurfaceOrientation",
72528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    "(Landroid/view/Surface;II)I",
72628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceOrientation },
72791838ded36131525312739c0929913b215519c2aRuben Brunk    { "nativeSetNextTimestamp",
72891838ded36131525312739c0929913b215519c2aRuben Brunk    "(Landroid/view/Surface;J)I",
72991838ded36131525312739c0929913b215519c2aRuben Brunk    (void *)LegacyCameraDevice_nativeSetNextTimestamp },
7301dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    { "nativeGetJpegFooterSize",
7311dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    "()I",
7321dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    (void *)LegacyCameraDevice_nativeGetJpegFooterSize },
733f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    { "nativeDetectSurfaceUsageFlags",
734f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    "(Landroid/view/Surface;)I",
735f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectSurfaceUsageFlags },
736feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk};
737feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
738feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk// Get all the required offsets in java class and register native functions
739feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkint register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env)
740feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk{
741feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // Register native functions
742feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return AndroidRuntime::registerNativeMethods(env,
743feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            CAMERA_DEVICE_CLASS_NAME,
744feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            gCameraDeviceMethods,
745feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            NELEM(gCameraDeviceMethods));
746feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
747