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
......@@ -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;
rc = VENDOR_CALL(device, start_preview);
if (gPreviewWindow != 0) {
rc = VENDOR_CALL(device, start_preview);
} else {
ALOGV("%s invalid preview window, defer start_preview", __FUNCTION__);
gPreviewStartDeferred = true;
}
return rc;
}
......@@ -219,7 +240,12 @@ static int camera2_preview_enabled(struct camera_device * device)
if(!device)
return -EINVAL;
return VENDOR_CALL(device, preview_enabled);
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;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment