Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5096defd authored by Igor Murashkin's avatar Igor Murashkin
Browse files

camera2: (legacy) Write the JPEG size as part of the blob transport

This fixes StillCaptureTest#testStillPreviewCombination

Change-Id: Ifbaae7828b2efcc1a768c77ce50718abd7f691d0
parent a296fece
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ public class RequestThreadManager {
    private static final int MSG_CLEANUP = 3;

    private static final int PREVIEW_FRAME_TIMEOUT = 300; // ms
    private static final int JPEG_FRAME_TIMEOUT = 1000; // ms
    private static final int JPEG_FRAME_TIMEOUT = 3000; // ms (same as CTS for API2)

    private static final float ASPECT_RATIO_TOLERANCE = 0.01f;
    private boolean mPreviewRunning = false;
@@ -401,6 +401,9 @@ public class RequestThreadManager {
        if (mPreviewTexture != null) {
            mPreviewTexture.setOnFrameAvailableListener(mPreviewCallback);
        }

        // TODO: configure the JPEG surface with some arbitrary size
        // using LegacyCameraDevice.nativeConfigureSurface
    }

    /**
+32 −4
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */

#define LOG_TAG "Legacy-CameraDevice-JNI"
// #define LOG_NDEBUG 0
#include <utils/Log.h>
#include <utils/Errors.h>
#include <utils/Trace.h>
@@ -26,6 +27,7 @@

#include <ui/GraphicBuffer.h>
#include <system/window.h>
#include <hardware/camera3.h>

using namespace android;

@@ -118,8 +120,9 @@ static status_t configureSurface(const sp<ANativeWindow>& anw,
        return err;
    }

    ALOGV("%s: Setting buffer count to %d", __FUNCTION__,
          maxBufferSlack + 1 + minUndequeuedBuffers);
    ALOGV("%s: Setting buffer count to %d, size to (%dx%d), fmt (0x%x)", __FUNCTION__,
          maxBufferSlack + 1 + minUndequeuedBuffers,
          width, height, pixelFmt);
    err = native_window_set_buffer_count(anw.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
    if (err != NO_ERROR) {
        ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
@@ -148,11 +151,29 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
                             int32_t width, // Width of the pixelBuffer
                             int32_t height, // Height of the pixelBuffer
                             int32_t pixelFmt, // Format of the pixelBuffer
                             int64_t bufSize) {
                             int32_t bufSize) {
    ATRACE_CALL();
    status_t err = NO_ERROR;
    ANativeWindowBuffer* anb;
    ALOGV("%s: Dequeue buffer from %p",__FUNCTION__, anw.get());
    ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
            __FUNCTION__, anw.get(), width, height, pixelFmt, bufSize);

    if (anw == 0) {
        ALOGE("%s: anw must not be NULL", __FUNCTION__);
        return BAD_VALUE;
    } else if (pixelBuffer == NULL) {
        ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__);
        return BAD_VALUE;
    } else if (width < 0) {
        ALOGE("%s: width must be non-negative", __FUNCTION__);
        return BAD_VALUE;
    } else if (height < 0) {
        ALOGE("%s: height must be non-negative", __FUNCTION__);
        return BAD_VALUE;
    } else if (bufSize < 0) {
        ALOGE("%s: bufSize must be non-negative", __FUNCTION__);
        return BAD_VALUE;
    }

    if (width < 0 || height < 0 || bufSize < 0) {
        ALOGE("%s: Illegal argument, negative dimension passed to produceFrame", __FUNCTION__);
@@ -163,6 +184,8 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
    err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
    if (err != NO_ERROR) return err;

    // TODO: check anb is large enough to store the results

    sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));

    switch(pixelFmt) {
@@ -257,7 +280,12 @@ static status_t produceFrame(const sp<ANativeWindow>& anw,
                        err);
                return err;
            }
            struct camera3_jpeg_blob footer = {
                jpeg_blob_id: CAMERA3_JPEG_BLOB_ID,
                jpeg_size: (uint32_t)width
            };
            memcpy(img, pixelBuffer, width);
            memcpy(img + anb->width - sizeof(footer), &footer, sizeof(footer));
            break;
        }
        default: {
+19 −0
Original line number Diff line number Diff line
@@ -33,6 +33,9 @@
#include <jni.h>
#include <JNIHelp.h>

#include <stdint.h>
#include <inttypes.h>

#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )

#define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID       "mNativeContext"
@@ -300,6 +303,14 @@ static uint32_t Image_getJpegSize(CpuConsumer::LockedBuffer* buffer)

    // failed to find size, default to whole buffer
    if (size == 0) {
        /*
         * This is a problem because not including the JPEG header
         * means that in certain rare situations a regular JPEG blob
         * will be misidentified as having a header, in which case
         * we will get a garbage size value.
         */
        ALOGW("%s: No JPEG header detected, defaulting to size=width=%d",
                __FUNCTION__, width);
        size = width;
    }

@@ -848,6 +859,14 @@ static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx)

    // Create byteBuffer from native buffer
    Image_getLockedBufferInfo(env, buffer, idx, &base, &size);

    if (size > static_cast<uint32_t>(INT32_MAX)) {
        // Byte buffer have 'int capacity', so check the range
        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
                "Size too large for bytebuffer capacity " PRIu32, size);
        return NULL;
    }

    byteBuffer = env->NewDirectByteBuffer(base, size);
    // TODO: throw dvm exOutOfMemoryError?
    if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) {