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

Commit 6c0586ea authored by Benoît Laniel's avatar Benoît Laniel Committed by Bernhard Thoben
Browse files

kitakami-common: camera: defer start_preview until surface is valid

Some apps like Snap start preview very early to setup camera while initializing
UI. It then calls setPreviewDisplay (set_preview_window) to define the surface
used for preview.

According to https://developer.android.com/reference/android/hardware/Camera.html#setPreviewDisplay%28android.view.SurfaceHolder%29
"This allows camera setup and surface creation to happen in parallel, saving time."

But https://developer.android.com/reference/android/hardware/Camera.html#startPreview%28%29
"Preview will not actually start until a surface is supplied with setPreviewDisplay(SurfaceHolder) or setPreviewTexture(SurfaceTexture)."

However, hero camera hal starts preview with an internal buffer when surface
is not valid / null.

[CAM_ID(0)][]-WARN(setPreviewWindow[204]):Preview window is NULL, create internal buffer for preview
[CAM_ID(0)][]-INFO(startPreview[519]):setBuffersThread is run

On the next set_preview_window call (the one defining the surface), camera hal
restarts preview since it is already running using the internal buffer.

[CAM_ID(0)][]-WRN(setPreviewWindow[187]):Preview is started, we forcely re-start preview

Problem with this is that it deadlocks quite often. It loops here

[CAM_ID(0)][]-INFO(m_mainThreadQSetup3AA[1078]):m_flagThreadStop(1)

Let's handle the situation in the wrapper so no restart is done by the hal.

Change-Id: I762af781e5af96b52407387aa9ae67874a8ab8b6
parent 3d27cfd3
Loading
Loading
Loading
Loading
+32 −4
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ typedef struct wrapper_camera2_device {
#define CAMERA_ID(device) (((wrapper_camera2_device_t *)(device))->id)

static camera_module_t *gVendorModule = 0;
static preview_stream_ops *gPreviewWindow = 0;
static bool gPreviewStartDeferred = false;

static camera_notify_callback gUserNotifyCb = NULL;
static camera_data_callback gUserDataCb = NULL;
@@ -111,12 +113,25 @@ static char * camera2_fixup_setparams(int id __unused, const char * settings)
static int camera2_set_preview_window(struct camera_device * device,
        struct preview_stream_ops *window)
{
    int rc = 0;
    ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, (uintptr_t)(((wrapper_camera2_device_t*)device)->vendor));

    if(!device || !window)
    if(!device)
        return -EINVAL;

    return VENDOR_CALL(device, set_preview_window, window);
    gPreviewWindow = window;

    if (gPreviewWindow != 0) {
        rc = VENDOR_CALL(device, set_preview_window, window);

        if (gPreviewStartDeferred) {
            ALOGV("%s call deferred start_preview", __FUNCTION__);
            gPreviewStartDeferred = false;
            VENDOR_CALL(device, start_preview);
        }
    }

    return rc;
}

void camera_notify_cb(int32_t msg_type, int32_t ext1, int32_t ext2, void *user) {
@@ -198,7 +213,13 @@ static int camera2_start_preview(struct camera_device * device)
    if(!device)
        return -EINVAL;

    if (gPreviewWindow != 0) {
        rc = VENDOR_CALL(device, start_preview);
    } else {
        ALOGV("%s invalid preview window, defer start_preview", __FUNCTION__);
        gPreviewStartDeferred = true;
    }

    return rc;
}

@@ -219,8 +240,13 @@ static int camera2_preview_enabled(struct camera_device * device)
    if(!device)
        return -EINVAL;

    if (gPreviewStartDeferred) {
        ALOGV("%s deferred start_preview, return 1", __FUNCTION__);
        return 1;
    } else {
        return VENDOR_CALL(device, preview_enabled);
    }
}

static int camera2_store_meta_data_in_buffers(struct camera_device * device, int enable)
{
@@ -427,6 +453,8 @@ static int camera2_device_close(hw_device_t* device)
        free(wrapper_dev->base.ops);
    free(wrapper_dev);
done:
    gPreviewWindow = 0;
    gPreviewStartDeferred = false;
    return ret;
}