android_hardware_camera2_legacy_LegacyCameraDevice.cpp revision 2a3ecce0a99e7684c6ef77fab1c5f0c2642af7d6
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"
252279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/JNIHelp.h>
26ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
27feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include "android_runtime/android_view_Surface.h"
2828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk#include "android_runtime/android_graphics_SurfaceTexture.h"
29feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
303c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk#include <gui/Surface.h>
313c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk#include <gui/IGraphicBufferProducer.h>
3229c3630563452c9635f0510d071839c112d3017dChien-Yu Chen#include <gui/IProducerListener.h>
33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include <ui/GraphicBuffer.h>
34feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include <system/window.h>
355096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin#include <hardware/camera3.h>
3628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk#include <system/camera_metadata.h>
37feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
383c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk#include <stdint.h>
393c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk#include <inttypes.h>
403c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
41feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkusing namespace android;
42feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
43feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk// fully-qualified class name
44feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#define CAMERA_DEVICE_CLASS_NAME "android/hardware/camera2/legacy/LegacyCameraDevice"
45feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#define CAMERA_DEVICE_BUFFER_SLACK  3
46ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk#define DONT_CARE 0
47feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
48feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
49feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
5091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
5191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
53433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk * Convert from RGB 888 to Y'CbCr using the conversion specified in JFIF v1.02
54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
5531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunkstatic void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane,
568973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk        uint8_t* crPlane, uint8_t* cbPlane, size_t chromaStep, size_t yStride, size_t chromaStride) {
57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    uint8_t R, G, B;
58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    size_t index = 0;
5931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    for (size_t j = 0; j < height; j++) {
608973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk        uint8_t* cr = crPlane;
618973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk        uint8_t* cb = cbPlane;
62433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk        uint8_t* y = yPlane;
63433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk        bool jEven = (j & 1) == 0;
6431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        for (size_t i = 0; i < width; i++) {
65feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            R = rgbBuf[index++];
66feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            G = rgbBuf[index++];
67feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            B = rgbBuf[index++];
68433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk            *y++ = (77 * R + 150 * G +  29 * B) >> 8;
69433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk            if (jEven && (i & 1) == 0) {
708973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk                *cb = (( -43 * R - 85 * G + 128 * B) >> 8) + 128;
718973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk                *cr = (( 128 * R - 107 * G - 21 * B) >> 8) + 128;
728973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk                cr += chromaStep;
738973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk                cb += chromaStep;
74feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // Skip alpha
76feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            index++;
77feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
78feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        yPlane += yStride;
79433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk        if (jEven) {
808973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk            crPlane += chromaStride;
818973597944890db9e7ad90a29ff8a44e6b2e2a7bRuben Brunk            cbPlane += chromaStride;
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;
90433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk    ALOGV("%s: yStride is: %zu, cStride is: %zu, cStep is: %zu", __FUNCTION__, yStride, cStride,
91433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk            cStep);
92feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    rgbToYuv420(rgbBuf, width, height, reinterpret_cast<uint8_t*>(ycbcr->y),
93433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk            reinterpret_cast<uint8_t*>(ycbcr->cr), reinterpret_cast<uint8_t*>(ycbcr->cb),
94feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            cStep, yStride, cStride);
95feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
96feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
9729c3630563452c9635f0510d071839c112d3017dChien-Yu Chenstatic status_t connectSurface(const sp<Surface>& surface, int32_t maxBufferSlack) {
98feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = NO_ERROR;
99feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
10029c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    err = surface->connect(NATIVE_WINDOW_API_CAMERA, /*listener*/NULL);
10129c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    if (err != OK) {
10229c3630563452c9635f0510d071839c112d3017dChien-Yu Chen        ALOGE("%s: Unable to connect to surface, error %s (%d).", __FUNCTION__,
103feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
104feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
105feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
106feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
10729c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    err = native_window_set_usage(surface.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
108feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
109feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__,
110feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
111feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
112feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
113feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
114feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int minUndequeuedBuffers;
11529c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    err = static_cast<ANativeWindow*>(surface.get())->query(surface.get(),
11629c3630563452c9635f0510d071839c112d3017dChien-Yu Chen            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
117feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
118feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).",
119feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                __FUNCTION__, strerror(-err), err);
120feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
121feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
122feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
12329c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    ALOGV("%s: Setting buffer count to %d", __FUNCTION__,
12429c3630563452c9635f0510d071839c112d3017dChien-Yu Chen            maxBufferSlack + 1 + minUndequeuedBuffers);
12529c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    err = native_window_set_buffer_count(surface.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
126feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
127feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
128feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
129feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
130feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
131feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return NO_ERROR;
132feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
133feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
134feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
135feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Produce a frame in the given surface.
136feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
137feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Args:
138feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    anw - a surface to produce a frame in.
139feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    pixelBuffer - image buffer to generate a frame from.
140feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    width - width of the pixelBuffer in pixels.
141feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    height - height of the pixelBuffer in pixels.
142feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    pixelFmt - format of the pixelBuffer, one of:
143feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *               HAL_PIXEL_FORMAT_YCrCb_420_SP,
144feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *               HAL_PIXEL_FORMAT_YCbCr_420_888,
145feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *               HAL_PIXEL_FORMAT_BLOB
146feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    bufSize - the size of the pixelBuffer in bytes.
147feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
148feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic status_t produceFrame(const sp<ANativeWindow>& anw,
149feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                             uint8_t* pixelBuffer,
15031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                             int32_t bufWidth, // Width of the pixelBuffer
15131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                             int32_t bufHeight, // Height of the pixelBuffer
152feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                             int32_t pixelFmt, // Format of the pixelBuffer
1535096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin                             int32_t bufSize) {
154feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ATRACE_CALL();
155feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = NO_ERROR;
156feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ANativeWindowBuffer* anb;
1575096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
15831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            __FUNCTION__, anw.get(), bufWidth, bufHeight, pixelFmt, bufSize);
1595096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin
1605096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    if (anw == 0) {
1615096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: anw must not be NULL", __FUNCTION__);
1625096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
1635096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    } else if (pixelBuffer == NULL) {
1645096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__);
1655096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
16631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    } else if (bufWidth < 0) {
1675096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: width must be non-negative", __FUNCTION__);
1685096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
16931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    } else if (bufHeight < 0) {
1705096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: height must be non-negative", __FUNCTION__);
1715096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
1725096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    } else if (bufSize < 0) {
1735096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: bufSize must be non-negative", __FUNCTION__);
1745096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
1755096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    }
176feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
17731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t width = static_cast<size_t>(bufWidth);
17831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t height = static_cast<size_t>(bufHeight);
17931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t bufferLength = static_cast<size_t>(bufSize);
18091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
181feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // TODO: Switch to using Surface::lock and Surface::unlockAndPost
182feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
183feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) return err;
184feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
185845eef05ffea53f4ce7a1e0551896be874c4f302Mathias Agopian    sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
1860c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    uint32_t grallocBufWidth = buf->getWidth();
1870c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    uint32_t grallocBufHeight = buf->getHeight();
1880c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    uint32_t grallocBufStride = buf->getStride();
1890c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    if (grallocBufWidth != width || grallocBufHeight != height) {
19031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32
1910c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk                ", expecting dimensions %zu x %zu",  __FUNCTION__, grallocBufWidth,
1920c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk                grallocBufHeight, width, height);
19331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        return BAD_VALUE;
19431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
19531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
19631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    int32_t bufFmt = 0;
19731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &bufFmt);
19831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    if (err != NO_ERROR) {
19931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__,
20031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                strerror(-err), err);
20131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        return err;
20231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
20331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
2040c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    uint64_t tmpSize = (pixelFmt == HAL_PIXEL_FORMAT_BLOB) ? grallocBufWidth :
2050c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk            4 * grallocBufHeight * grallocBufWidth;
20631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    if (bufFmt != pixelFmt) {
20731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        if (bufFmt == HAL_PIXEL_FORMAT_RGBA_8888 && pixelFmt == HAL_PIXEL_FORMAT_BLOB) {
20831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            ALOGV("%s: Using BLOB to RGBA format override.", __FUNCTION__);
2090c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk            tmpSize = 4 * (grallocBufWidth + grallocBufStride * (grallocBufHeight - 1));
21031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        } else {
21131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            ALOGW("%s: Format mismatch in produceFrame: expecting format %#" PRIx32
21231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                    ", but received buffer with format %#" PRIx32, __FUNCTION__, pixelFmt, bufFmt);
21331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        }
21431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
21531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
21631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    if (tmpSize > SIZE_MAX) {
21731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        ALOGE("%s: Overflow calculating size, buffer with dimens %zu x %zu is absurdly large...",
21831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                __FUNCTION__, width, height);
21931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        return BAD_VALUE;
22031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
22131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
22231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t totalSizeBytes = tmpSize;
223feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
224433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk    ALOGV("%s: Pixel format chosen: %x", __FUNCTION__, pixelFmt);
225feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    switch(pixelFmt) {
226feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
22731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (bufferLength < totalSizeBytes) {
22831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
22931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, bufferLength);
230feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return BAD_VALUE;
231feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
232feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* img = NULL;
233feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
234feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
235feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (err != NO_ERROR) return err;
236feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
237feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* yPlane = img;
238feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* uPlane = img + height * width;
239feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* vPlane = uPlane + 1;
240feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            size_t chromaStep = 2;
241feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            size_t yStride = width;
242feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            size_t chromaStride = width;
243feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
244feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            rgbToYuv420(pixelBuffer, width, height, yPlane,
245feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    uPlane, vPlane, chromaStep, yStride, chromaStride);
246feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            break;
247feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
24891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk        case HAL_PIXEL_FORMAT_YV12: {
24931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (bufferLength < totalSizeBytes) {
25031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
25131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, bufferLength);
25291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                return BAD_VALUE;
25391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            }
25491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
25591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            if ((width & 1) || (height & 1)) {
25631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height);
25791b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                return BAD_VALUE;
25891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            }
25991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
26091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* img = NULL;
26191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
26291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
26391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            if (err != NO_ERROR) {
26491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                ALOGE("%s: Error %s (%d) while locking gralloc buffer for write.", __FUNCTION__,
26591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                        strerror(-err), err);
26691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                return err;
26791b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            }
26891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
26991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint32_t stride = buf->getStride();
270433e715cc0040ce22a31964c71bff71b1fe1a14fRuben Brunk            ALOGV("%s: stride is: %" PRIu32, __FUNCTION__, stride);
27191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            LOG_ALWAYS_FATAL_IF(stride % 16, "Stride is not 16 pixel aligned %d", stride);
27291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
27391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint32_t cStride = ALIGN(stride / 2, 16);
27491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            size_t chromaStep = 1;
27591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
27691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* yPlane = img;
27791b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* crPlane = img + static_cast<uint32_t>(height) * stride;
27891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* cbPlane = crPlane + cStride * static_cast<uint32_t>(height) / 2;
27991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
28091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            rgbToYuv420(pixelBuffer, width, height, yPlane,
28191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                    crPlane, cbPlane, chromaStep, stride, cStride);
28291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            break;
28391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk        }
284feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        case HAL_PIXEL_FORMAT_YCbCr_420_888: {
285feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // Software writes with YCbCr_420_888 format are unsupported
286feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // by the gralloc module for now
28731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (bufferLength < totalSizeBytes) {
28831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
28931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, bufferLength);
290feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return BAD_VALUE;
291feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
292feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            android_ycbcr ycbcr = android_ycbcr();
293feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
294feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
295feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            err = buf->lockYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr);
296feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (err != NO_ERROR) {
297feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                ALOGE("%s: Failed to lock ycbcr buffer, error %s (%d).", __FUNCTION__,
298feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        strerror(-err), err);
299feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return err;
300feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
301feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            rgbToYuv420(pixelBuffer, width, height, &ycbcr);
302feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            break;
303feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
304feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        case HAL_PIXEL_FORMAT_BLOB: {
305feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int8_t* img = NULL;
3060fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk            struct camera3_jpeg_blob footer = {
307452efb218eb9af6ab2763879645bfc92db8ba02aBernhard Rosenkränzer                .jpeg_blob_id = CAMERA3_JPEG_BLOB_ID,
308452efb218eb9af6ab2763879645bfc92db8ba02aBernhard Rosenkränzer                .jpeg_size = (uint32_t)bufferLength
3090fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk            };
3100fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk
31131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            size_t totalJpegSize = bufferLength + sizeof(footer);
31231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble
31331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
31431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (totalJpegSize > totalSizeBytes) {
31531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: Pixel buffer needs size %zu, cannot fit in gralloc buffer of size %zu",
31631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, totalJpegSize, totalSizeBytes);
3170fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk                return BAD_VALUE;
3180fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk            }
319feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
320feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
321feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (err != NO_ERROR) {
322feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                ALOGE("%s: Failed to lock buffer, error %s (%d).", __FUNCTION__, strerror(-err),
323feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        err);
324feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return err;
325feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
32631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
32731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            memcpy(img, pixelBuffer, bufferLength);
32831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            memcpy(img + totalSizeBytes - sizeof(footer), &footer, sizeof(footer));
329feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            break;
330feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
331feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        default: {
332feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            ALOGE("%s: Invalid pixel format in produceFrame: %x", __FUNCTION__, pixelFmt);
333feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            return BAD_VALUE;
334feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
335feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
336feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
337feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("%s: Unlock buffer from %p", __FUNCTION__, anw.get());
338feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = buf->unlock();
339feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
340feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to unlock buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
341feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
342feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
343feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
344feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("%s: Queue buffer to %p", __FUNCTION__, anw.get());
345feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), /*fenceFd*/-1);
346feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
347feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to queue buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
348feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
349feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
350feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return NO_ERROR;
351feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
352feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
353feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic sp<ANativeWindow> getNativeWindow(JNIEnv* env, jobject surface) {
354feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
355feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (surface) {
356feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        anw = android_view_Surface_getNativeWindow(env, surface);
357feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (env->ExceptionCheck()) {
3583c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk            return NULL;
359feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
360feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    } else {
361feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowNullPointerException(env, "surface");
3623c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
363feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
364feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (anw == NULL) {
365443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk        ALOGE("%s: Surface had no valid native window.", __FUNCTION__);
3663c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
367feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
368feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return anw;
369feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
370feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
37128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic sp<ANativeWindow> getNativeWindowFromTexture(JNIEnv* env, jobject surfaceTexture) {
37228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
37328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (surfaceTexture) {
37428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        anw = android_SurfaceTexture_getNativeWindow(env, surfaceTexture);
37528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        if (env->ExceptionCheck()) {
37628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk            return NULL;
37728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        }
37828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    } else {
37928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jniThrowNullPointerException(env, "surfaceTexture");
38028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return NULL;
38128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
38228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (anw == NULL) {
38328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
38428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                "SurfaceTexture had no valid native window.");
38528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return NULL;
38628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
38728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return anw;
38828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
38928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
3903c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkstatic sp<Surface> getSurface(JNIEnv* env, jobject surface) {
3913c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<Surface> s;
3923c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (surface) {
3933c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        s = android_view_Surface_getSurface(env, surface);
3943c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        if (env->ExceptionCheck()) {
3953c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk            return NULL;
3963c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        }
3973c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    } else {
3983c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        jniThrowNullPointerException(env, "surface");
3993c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
4003c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
4013c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (s == NULL) {
4023c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
4033c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk                "Surface had no valid native Surface.");
4043c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
4053c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
4063c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    return s;
4073c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk}
4083c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
409feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkextern "C" {
410feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
411feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) {
412feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeDetectSurfaceType");
413feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
414feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
415feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
416ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
417feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
418feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int32_t fmt = 0;
419feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt);
420feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if(err != NO_ERROR) {
421ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err),
422ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                err);
423ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
424feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
425feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return fmt;
426feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
427feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
428e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvalastatic jint LegacyCameraDevice_nativeDetectSurfaceDataspace(JNIEnv* env, jobject thiz, jobject surface) {
429e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    ALOGV("nativeDetectSurfaceDataspace");
430e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    sp<ANativeWindow> anw;
431e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    if ((anw = getNativeWindow(env, surface)) == NULL) {
432e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
433e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala        return BAD_VALUE;
434e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    }
435e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    int32_t fmt = 0;
436e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    status_t err = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE, &fmt);
437e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    if(err != NO_ERROR) {
438e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala        ALOGE("%s: Error while querying surface dataspace  %s (%d).", __FUNCTION__, strerror(-err),
439e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala                err);
440e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala        return err;
441e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    }
442e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    return fmt;
443e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala}
444e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala
445ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz,
446feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk          jobject surface, jintArray dimens) {
447feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeGetSurfaceDimens");
44828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
44928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (dimens == NULL) {
45028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Null dimens argument passed to nativeDetectSurfaceDimens", __FUNCTION__);
45128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
45228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
45328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
45428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (env->GetArrayLength(dimens) < 2) {
45528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Invalid length of dimens argument in nativeDetectSurfaceDimens", __FUNCTION__);
45628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
45728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
45828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
459feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
460feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
461feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
462ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
463feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
464feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int32_t dimenBuf[2];
465feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
466feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if(err != NO_ERROR) {
467ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err),
468ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                err);
469ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
470feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
471feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
472feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if(err != NO_ERROR) {
473ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while querying surface height %s (%d).", __FUNCTION__, strerror(-err),
474ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                err);
475ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
476feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
477feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
478ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
479feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
480feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
481f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunkstatic jint LegacyCameraDevice_nativeDetectSurfaceUsageFlags(JNIEnv* env, jobject thiz,
482f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk          jobject surface) {
483f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    ALOGV("nativeDetectSurfaceUsageFlags");
484f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk
485f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    sp<ANativeWindow> anw;
486f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
4872a3ecce0a99e7684c6ef77fab1c5f0c2642af7d6Yin-Chia Yeh        jniThrowException(env, "java/lang/UnsupportedOperationException;",
488f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk            "Could not retrieve native window from surface.");
489f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        return BAD_VALUE;
490f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    }
491f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    int32_t usage = 0;
492f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
493f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    if(err != NO_ERROR) {
4942a3ecce0a99e7684c6ef77fab1c5f0c2642af7d6Yin-Chia Yeh        jniThrowException(env, "java/lang/UnsupportedOperationException;",
495f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk            "Error while querying surface usage bits");
496f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        return err;
497f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    }
498f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    return usage;
499f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk}
500f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk
50129c3630563452c9635f0510d071839c112d3017dChien-Yu Chenstatic jint LegacyCameraDevice_nativeDisconnectSurface(JNIEnv* env, jobject thiz,
50229c3630563452c9635f0510d071839c112d3017dChien-Yu Chen          jobject surface) {
50329c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    ALOGV("nativeDisconnectSurface");
50429c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    if (surface == nullptr) return NO_ERROR;
50529c3630563452c9635f0510d071839c112d3017dChien-Yu Chen
50629c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    sp<ANativeWindow> anw;
50729c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    if ((anw = getNativeWindow(env, surface)) == NULL) {
50829c3630563452c9635f0510d071839c112d3017dChien-Yu Chen        ALOGV("Buffer queue has already been abandoned.");
50929c3630563452c9635f0510d071839c112d3017dChien-Yu Chen        return NO_ERROR;
51029c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    }
51129c3630563452c9635f0510d071839c112d3017dChien-Yu Chen
51229c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    status_t err = native_window_api_disconnect(anw.get(), NATIVE_WINDOW_API_CAMERA);
51329c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    if(err != NO_ERROR) {
5142a3ecce0a99e7684c6ef77fab1c5f0c2642af7d6Yin-Chia Yeh        jniThrowException(env, "java/lang/UnsupportedOperationException;",
51529c3630563452c9635f0510d071839c112d3017dChien-Yu Chen            "Error while disconnecting surface");
51629c3630563452c9635f0510d071839c112d3017dChien-Yu Chen        return err;
51729c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    }
51829c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    return NO_ERROR;
51929c3630563452c9635f0510d071839c112d3017dChien-Yu Chen}
52029c3630563452c9635f0510d071839c112d3017dChien-Yu Chen
52128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz,
52228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jobject surfaceTexture, jintArray dimens) {
52328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("nativeDetectTextureDimens");
52428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
52528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if ((anw = getNativeWindowFromTexture(env, surfaceTexture)) == NULL) {
52628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Could not retrieve native window from SurfaceTexture.", __FUNCTION__);
52728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
52828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
52928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
53028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t dimenBuf[2];
53128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
53228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if(err != NO_ERROR) {
53328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Error while querying SurfaceTexture width %s (%d)", __FUNCTION__,
53428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
53528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
53628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
53728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
53828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
53928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if(err != NO_ERROR) {
54028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Error while querying SurfaceTexture height %s (%d)", __FUNCTION__,
54128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
54228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
54328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
54428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
54528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
54628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (env->ExceptionCheck()) {
54728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
54828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
54928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return NO_ERROR;
55028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
55128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
55229c3630563452c9635f0510d071839c112d3017dChien-Yu Chenstatic jint LegacyCameraDevice_nativeConnectSurface(JNIEnv* env, jobject thiz, jobject surface) {
55329c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    ALOGV("nativeConnectSurface");
55429c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    sp<Surface> s;
55529c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    if ((s = getSurface(env, surface)) == NULL) {
55629c3630563452c9635f0510d071839c112d3017dChien-Yu Chen        ALOGE("%s: Could not retrieve surface.", __FUNCTION__);
557ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
558feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
55929c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    status_t err = connectSurface(s, CAMERA_DEVICE_BUFFER_SLACK);
560feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
561ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
562ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
563feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
564ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
565feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
566feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
567ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface,
568feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) {
569feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeProduceFrame");
570feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
571feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
572feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
573feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
574ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
575feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
576feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
577feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (pixelBuffer == NULL) {
578feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowNullPointerException(env, "pixelBuffer");
579ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return DONT_CARE;
580feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
581feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
582feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer));
583feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL);
584feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
585feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (pixels == NULL) {
586feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowNullPointerException(env, "pixels");
587ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return DONT_CARE;
588feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
589feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
590feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height,
591feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            pixelFormat, bufSize);
592feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT);
593feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
594feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
595ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err);
596ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
597feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
598ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
599feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
600feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
601ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface,
602feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint pixelFormat) {
603feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeSetSurfaceType");
604feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
605feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
606feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
607ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
608feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
609feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = native_window_set_buffers_format(anw.get(), pixelFormat);
610feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
611ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err);
612ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
613feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
614ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
615feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
616feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
617ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface,
618feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint width, jint height) {
619feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeSetSurfaceDimens");
620feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
621feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
622feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
623ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
624feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
625a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk
626b0acf7fcfab08b5af1f99daa51bedbb659d18926Eino-Ville Talvala    // Set user dimensions only
627b0acf7fcfab08b5af1f99daa51bedbb659d18926Eino-Ville Talvala    // The producer dimensions are owned by GL
628b0acf7fcfab08b5af1f99daa51bedbb659d18926Eino-Ville Talvala    status_t err = native_window_set_buffers_user_dimensions(anw.get(), width, height);
629a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    if (err != NO_ERROR) {
630a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk        ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err),
631a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk                err);
632a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk        return err;
633a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    }
634ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
635feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
636feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
6373c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkstatic jlong LegacyCameraDevice_nativeGetSurfaceId(JNIEnv* env, jobject thiz, jobject surface) {
6383c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    ALOGV("nativeGetSurfaceId");
6393c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<Surface> s;
6403c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if ((s = getSurface(env, surface)) == NULL) {
6413c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve native Surface from surface.", __FUNCTION__);
6423c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6433c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6443c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<IGraphicBufferProducer> gbp = s->getIGraphicBufferProducer();
6453c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (gbp == NULL) {
6463c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve IGraphicBufferProducer from surface.", __FUNCTION__);
6473c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6483c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
64997069dd4fd5454ba057ccf2854d7f925c337884cMarco Nelissen    sp<IBinder> b = IInterface::asBinder(gbp);
6503c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (b == NULL) {
6513c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve IBinder from surface.", __FUNCTION__);
6523c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6533c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6543c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    /*
6553c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     * FIXME: Use better unique ID for surfaces than native IBinder pointer.  Fix also in the camera
6563c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     * service (CameraDeviceClient.h).
6573c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     */
6583c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    return reinterpret_cast<jlong>(b.get());
6593c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk}
6603c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
66128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv* env, jobject thiz,
66228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jobject surface, jint facing, jint orientation) {
66328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("nativeSetSurfaceOrientation");
66428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
66528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
66628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
66728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
66828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
66928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
67028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    status_t err = NO_ERROR;
67128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    CameraMetadata staticMetadata;
67228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
67328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t orientVal = static_cast<int32_t>(orientation);
67428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    uint8_t facingVal = static_cast<uint8_t>(facing);
67528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1);
67628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1);
67728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
67828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t transform = 0;
67928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
68091838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) {
68128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Invalid rotation transform %s (%d)", __FUNCTION__, strerror(-err),
68228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                err);
68328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
68428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
68528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
68628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("%s: Setting buffer sticky transform to %d", __FUNCTION__, transform);
68728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
68891838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) {
68928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Unable to configure surface transform, error %s (%d)", __FUNCTION__,
69028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
69128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
69228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
69328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
69428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return NO_ERROR;
69528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
69628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
69791838ded36131525312739c0929913b215519c2aRuben Brunkstatic jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz, jobject surface,
69891838ded36131525312739c0929913b215519c2aRuben Brunk        jlong timestamp) {
69991838ded36131525312739c0929913b215519c2aRuben Brunk    ALOGV("nativeSetNextTimestamp");
70091838ded36131525312739c0929913b215519c2aRuben Brunk    sp<ANativeWindow> anw;
70191838ded36131525312739c0929913b215519c2aRuben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
70291838ded36131525312739c0929913b215519c2aRuben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
70391838ded36131525312739c0929913b215519c2aRuben Brunk        return BAD_VALUE;
70491838ded36131525312739c0929913b215519c2aRuben Brunk    }
70591838ded36131525312739c0929913b215519c2aRuben Brunk
70691838ded36131525312739c0929913b215519c2aRuben Brunk    status_t err = NO_ERROR;
70791838ded36131525312739c0929913b215519c2aRuben Brunk
70891838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = native_window_set_buffers_timestamp(anw.get(), static_cast<int64_t>(timestamp))) !=
70991838ded36131525312739c0929913b215519c2aRuben Brunk            NO_ERROR) {
71091838ded36131525312739c0929913b215519c2aRuben Brunk        ALOGE("%s: Unable to set surface timestamp, error %s (%d)", __FUNCTION__, strerror(-err),
71191838ded36131525312739c0929913b215519c2aRuben Brunk                err);
71291838ded36131525312739c0929913b215519c2aRuben Brunk        return err;
71391838ded36131525312739c0929913b215519c2aRuben Brunk    }
71491838ded36131525312739c0929913b215519c2aRuben Brunk    return NO_ERROR;
71591838ded36131525312739c0929913b215519c2aRuben Brunk}
71691838ded36131525312739c0929913b215519c2aRuben Brunk
717a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunkstatic jint LegacyCameraDevice_nativeSetScalingMode(JNIEnv* env, jobject thiz, jobject surface,
718a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk        jint mode) {
719a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    ALOGV("nativeSetScalingMode");
720a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    sp<ANativeWindow> anw;
721a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
722a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
723a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk        return BAD_VALUE;
724a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    }
725a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    status_t err = NO_ERROR;
726a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    if ((err = native_window_set_scaling_mode(anw.get(), static_cast<int>(mode))) != NO_ERROR) {
727a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk        ALOGE("%s: Unable to set surface scaling mode, error %s (%d)", __FUNCTION__,
728a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk                strerror(-err), err);
729a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk        return err;
730a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    }
731a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    return NO_ERROR;
732a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk}
733a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk
7341dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunkstatic jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) {
7351dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    ALOGV("nativeGetJpegFooterSize");
7361dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    return static_cast<jint>(sizeof(struct camera3_jpeg_blob));
7371dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk}
7381dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk
739feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk} // extern "C"
740feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
74176f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gCameraDeviceMethods[] = {
742feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeDetectSurfaceType",
743feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    "(Landroid/view/Surface;)I",
744feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectSurfaceType },
745e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    { "nativeDetectSurfaceDataspace",
746e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    "(Landroid/view/Surface;)I",
747e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    (void *)LegacyCameraDevice_nativeDetectSurfaceDataspace },
748feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeDetectSurfaceDimens",
749ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;[I)I",
750feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
75129c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    { "nativeConnectSurface",
75229c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    "(Landroid/view/Surface;)I",
75329c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    (void *)LegacyCameraDevice_nativeConnectSurface },
754feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeProduceFrame",
755ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;[BIII)I",
756feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeProduceFrame },
757feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeSetSurfaceFormat",
758ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;I)I",
759feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceFormat },
760feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeSetSurfaceDimens",
761ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;II)I",
762feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceDimens },
7633c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    { "nativeGetSurfaceId",
7643c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    "(Landroid/view/Surface;)J",
7653c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    (void *)LegacyCameraDevice_nativeGetSurfaceId },
76628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    { "nativeDetectTextureDimens",
76728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    "(Landroid/graphics/SurfaceTexture;[I)I",
76828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectTextureDimens },
76928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    { "nativeSetSurfaceOrientation",
77028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    "(Landroid/view/Surface;II)I",
77128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceOrientation },
77291838ded36131525312739c0929913b215519c2aRuben Brunk    { "nativeSetNextTimestamp",
77391838ded36131525312739c0929913b215519c2aRuben Brunk    "(Landroid/view/Surface;J)I",
77491838ded36131525312739c0929913b215519c2aRuben Brunk    (void *)LegacyCameraDevice_nativeSetNextTimestamp },
7751dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    { "nativeGetJpegFooterSize",
7761dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    "()I",
7771dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    (void *)LegacyCameraDevice_nativeGetJpegFooterSize },
778f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    { "nativeDetectSurfaceUsageFlags",
779f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    "(Landroid/view/Surface;)I",
780f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectSurfaceUsageFlags },
781a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    { "nativeSetScalingMode",
782a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    "(Landroid/view/Surface;I)I",
783a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    (void *)LegacyCameraDevice_nativeSetScalingMode },
78429c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    { "nativeDisconnectSurface",
78529c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    "(Landroid/view/Surface;)I",
78629c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    (void *)LegacyCameraDevice_nativeDisconnectSurface },
787feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk};
788feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
789feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk// Get all the required offsets in java class and register native functions
790feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkint register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env)
791feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk{
792feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // Register native functions
793ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return RegisterMethodsOrDie(env,
794feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            CAMERA_DEVICE_CLASS_NAME,
795feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            gCameraDeviceMethods,
796feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            NELEM(gCameraDeviceMethods));
797feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
798