Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix a whole bunch of things

Support for multiple cameras.
Add software decoding support
Fix barcode scanners memory leak
Fix 30sec video recording limit issue caused by memory leak
Add support for HWA ROMs (tested only on HD2)
  • Loading branch information...
commit 903d325fc65b220902a476be260a387117f30f32 1 parent d076eb6
rapmv78 authored
Showing with 977 additions and 20 deletions.
  1. +2 −2 Android.mk
  2. +162 −18 cameraHal.cpp
  3. +813 −0 cameraHal.cpp.orig
4 Android.mk
View
@@ -17,8 +17,8 @@ CAMERA_LIB := camera-nexus
endif
TARGET_GLOBAL_LD_DIRS += -L$(LOCAL_PATH) -l${CAMERA_LIB}
-LOCAL_SHARED_LIBRARIES := liblog libdl libutils libcamera_client libbinder libcutils libhardware
+LOCAL_SHARED_LIBRARIES := liblog libdl libutils libcamera_client libbinder libcutils libhardware libui
LOCAL_C_INCLUDES := frameworks/base/services/ frameworks/base/include
-LOCAL_C_INCLUDES += hardware/libhardware/include/ hardware/libhardware/modules/gralloc/
+LOCAL_C_INCLUDES += hardware/libhardware/include/ hardware
include $(BUILD_SHARED_LIBRARY)
180 cameraHal.cpp
View
@@ -23,11 +23,21 @@
#include <fcntl.h>
#include <linux/ioctl.h>
#include <linux/msm_mdp.h>
-#include <gralloc_priv.h>
+#include <ui/Rect.h>
+#include <ui/GraphicBufferMapper.h>
+#include <dlfcn.h>
#define NO_ERROR 0
-//#define LOGV LOGI
#define GRALLOC_USAGE_PMEM_PRIVATE_ADSP GRALLOC_USAGE_PRIVATE_0
+#define MSM_COPY_HW 1
+#define HWA 1
+#ifdef HWA
+#include "qcom/display/libgralloc/gralloc_priv.h"
+#else
+#include "libhardware/modules/gralloc/gralloc_priv.h"
+#endif
+
+//#define LOGV LOGI
struct qcom_mdp_rect {
uint32_t x;
@@ -60,7 +70,9 @@ struct blitreq {
};
/* Prototypes and extern functions. */
-extern "C" android::sp<android::CameraHardwareInterface> openCameraHardware(int id);
+android::sp<android::CameraHardwareInterface> (*LINK_openCameraHardware)(int id);
+int (*LINK_getNumberofCameras)(void);
+void (*LINK_getCameraInfo)(int cameraId, struct camera_info *info);
int qcamera_device_open(const hw_module_t* module, const char* name,
hw_device_t** device);
int CameraHAL_GetNum_Cameras(void);
@@ -109,18 +121,23 @@ CameraHAL_NotifyCb(int32_t msg_type, int32_t ext1,
}
}
-void
+bool
CameraHAL_CopyBuffers_Hw(int srcFd, int destFd,
size_t srcOffset, size_t destOffset,
int srcFormat, int destFormat,
int x, int y, int w, int h)
{
struct blitreq blit;
+ bool success = true;
int fb_fd = open("/dev/graphics/fb0", O_RDWR);
+#ifndef MSM_COPY_HW
+ return false;
+#endif
+
if (fb_fd < 0) {
LOGD("CameraHAL_CopyBuffers_Hw: Error opening /dev/graphics/fb0\n");
- return;
+ return false;
}
LOGV("CameraHAL_CopyBuffers_Hw: srcFD:%d destFD:%d srcOffset:%#x"
@@ -152,13 +169,49 @@ CameraHAL_CopyBuffers_Hw(int srcFd, int destFd,
blit.req.src_rect.h = blit.req.dst_rect.h = h;
if (ioctl(fb_fd, MSMFB_BLIT, &blit)) {
- LOGE("CameraHAL_CopyBuffers_Hw: MSMFB_BLIT failed = %d %s\n",
+ LOGV("CameraHAL_CopyBuffers_Hw: MSMFB_BLIT failed = %d %s\n",
errno, strerror(errno));
+ success = false;
}
close(fb_fd);
+ return success;
}
void
+CameraHal_Decode_Sw(unsigned int* rgb, char* yuv420sp, int width, int height)
+{
+ int frameSize = width * height;
+
+ if (!qCamera->previewEnabled()) return;
+
+ for (int j = 0, yp = 0; j < height; j++) {
+ int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
+ for (int i = 0; i < width; i++, yp++) {
+ int y = (0xff & ((int) yuv420sp[yp])) - 16;
+ if (y < 0) y = 0;
+ if ((i & 1) == 0) {
+ v = (0xff & yuv420sp[uvp++]) - 128;
+ u = (0xff & yuv420sp[uvp++]) - 128;
+ }
+
+ int y1192 = 1192 * y;
+ int r = (y1192 + 1634 * v);
+ int g = (y1192 - 833 * v - 400 * u);
+ int b = (y1192 + 2066 * u);
+
+ if (r < 0) r = 0; else if (r > 262143) r = 262143;
+ if (g < 0) g = 0; else if (g > 262143) g = 262143;
+ if (b < 0) b = 0; else if (b > 262143) b = 262143;
+
+ rgb[yp] = 0xff000000 | ((b << 6) & 0xff0000) |
+ ((g >> 2) & 0xff00) | ((r >> 10) & 0xff);
+ }
+ }
+}
+
+
+
+void
CameraHAL_CopyBuffers_Sw(char *dest, char *src, int size)
{
int i;
@@ -184,7 +237,7 @@ CameraHAL_CopyBuffers_Sw(char *dest, char *src, int size)
}
void
-CameraHAL_HandlePreviewData(const android::sp<android::IMemory>& dataPtr,
+CameraHAL_HandlePreviewData(const android::sp<android::IMemory>& dataPtr,
preview_stream_ops_t *mWindow,
camera_request_memory getMemory,
int32_t previewWidth, int32_t previewHeight)
@@ -193,7 +246,11 @@ CameraHAL_HandlePreviewData(const android::sp<android::IMemory>& dataPtr,
ssize_t offset;
size_t size;
int32_t previewFormat = MDP_Y_CBCR_H2V2;
+#ifdef HWA
+ int32_t destFormat = MDP_RGBX_8888;
+#else
int32_t destFormat = MDP_RGBA_8888;
+#endif
android::status_t retVal;
android::sp<android::IMemoryHeap> mHeap = dataPtr->getMemory(&offset,
@@ -204,11 +261,18 @@ CameraHAL_HandlePreviewData(const android::sp<android::IMemory>& dataPtr,
(unsigned)offset, size, mHeap != NULL ? mHeap->base() : 0);
mWindow->set_usage(mWindow,
+#ifndef HWA
GRALLOC_USAGE_PMEM_PRIVATE_ADSP |
+#endif
GRALLOC_USAGE_SW_READ_OFTEN);
retVal = mWindow->set_buffers_geometry(mWindow,
previewWidth, previewHeight,
- HAL_PIXEL_FORMAT_RGBA_8888);
+#ifdef HWA
+ HAL_PIXEL_FORMAT_RGBX_8888
+#else
+ HAL_PIXEL_FORMAT_RGBA_8888
+#endif
+ );
if (retVal == NO_ERROR) {
int32_t stride;
buffer_handle_t *bufHandle = NULL;
@@ -220,10 +284,32 @@ CameraHAL_HandlePreviewData(const android::sp<android::IMemory>& dataPtr,
if (retVal == NO_ERROR) {
private_handle_t const *privHandle =
reinterpret_cast<private_handle_t const *>(*bufHandle);
- CameraHAL_CopyBuffers_Hw(mHeap->getHeapID(), privHandle->fd,
- offset, privHandle->offset,
- previewFormat, destFormat,
- 0, 0, previewWidth, previewHeight);
+ if (!CameraHAL_CopyBuffers_Hw(mHeap->getHeapID(), privHandle->fd,
+ offset, privHandle->offset,
+ previewFormat, destFormat,
+ 0, 0, previewWidth,
+ previewHeight)) {
+ void *bits;
+ android::Rect bounds;
+ android::GraphicBufferMapper &mapper =
+ android::GraphicBufferMapper::get();
+
+ bounds.left = 0;
+ bounds.top = 0;
+ bounds.right = previewWidth;
+ bounds.bottom = previewHeight;
+
+ mapper.lock(*bufHandle, GRALLOC_USAGE_SW_READ_OFTEN, bounds,
+ &bits);
+ LOGV("CameraHAL_HPD: w:%d h:%d bits:%p",
+ previewWidth, previewHeight, bits);
+ CameraHal_Decode_Sw((unsigned int *)bits, (char *)mHeap->base() + offset,
+ previewWidth, previewHeight);
+
+ // unlock buffer before sending to display
+ mapper.unlock(*bufHandle);
+ }
+
mWindow->enqueue_buffer(mWindow, bufHandle);
LOGV("CameraHAL_HandlePreviewData: enqueued buffer\n");
} else {
@@ -252,7 +338,7 @@ CameraHAL_GenClientData(const android::sp<android::IMemory> &dataPtr,
clientData = reqClientMemory(-1, size, 1, user);
if (clientData != NULL) {
- CameraHAL_CopyBuffers_Sw((char *)clientData->data,
+ CameraHAL_CopyBuffers_Sw((char *)clientData->data,
(char *)(mHeap->base()) + offset, size);
} else {
LOGV("CameraHAL_GenClientData: ERROR allocating memory from client\n");
@@ -272,12 +358,14 @@ CameraHAL_DataCb(int32_t msg_type, const android::sp<android::IMemory>& dataPtr,
CameraHAL_HandlePreviewData(dataPtr, mWindow, origCamReqMemory,
previewWidth, previewHeight);
}
+
if (origData_cb != NULL && origCamReqMemory != NULL) {
camera_memory_t *clientData = CameraHAL_GenClientData(dataPtr,
origCamReqMemory, user);
if (clientData != NULL) {
LOGV("CameraHAL_DataCb: Posting data to client\n");
origData_cb(msg_type, clientData, 0, NULL, user);
+ clientData->release(clientData);
}
}
}
@@ -297,6 +385,7 @@ CameraHAL_DataTSCb(nsecs_t timestamp, int32_t msg_type,
systemTime());
origDataTS_cb(timestamp, msg_type, clientData, 0, user);
qCamera->releaseRecordingFrame(dataPtr);
+ clientData->release(clientData);
} else {
LOGD("CameraHAL_DataTSCb: ERROR allocating memory from client\n");
}
@@ -306,16 +395,48 @@ CameraHAL_DataTSCb(nsecs_t timestamp, int32_t msg_type,
int
CameraHAL_GetNum_Cameras(void)
{
+ int numCameras = 1;
+
LOGE("CameraHAL_GetNum_Cameras:\n");
- return 1;
+ void *libcameraHandle = ::dlopen("libcamera.so", RTLD_NOW);
+ LOGD("CameraHAL_GetNum_Cameras: loading libcamera at %p", libcameraHandle);
+ if (!libcameraHandle) {
+ LOGE("FATAL ERROR: could not dlopen libcamera.so: %s", dlerror());
+ } else {
+ if (::dlsym(libcameraHandle, "HAL_getNumberOfCameras") != NULL) {
+ *(void**)&LINK_getNumberofCameras =
+ ::dlsym(libcameraHandle, "HAL_getNumberOfCameras");
+ numCameras = LINK_getNumberofCameras();
+ LOGD("CameraHAL_GetNum_Cameras: numCameras:%d", numCameras);
+ }
+ dlclose(libcameraHandle);
+ }
+ return numCameras;
}
int
CameraHAL_GetCam_Info(int camera_id, struct camera_info *info)
{
+ bool dynamic = false;
LOGV("CameraHAL_GetCam_Info:\n");
- info->facing = CAMERA_FACING_BACK;
- info->orientation = 90;
+ void *libcameraHandle = ::dlopen("libcamera.so", RTLD_NOW);
+ LOGD("CameraHAL_GetNum_Cameras: loading libcamera at %p", libcameraHandle);
+ if (!libcameraHandle) {
+ LOGE("FATAL ERROR: could not dlopen libcamera.so: %s", dlerror());
+ return EINVAL;
+ } else {
+ if (::dlsym(libcameraHandle, "HAL_getCameraInfo") != NULL) {
+ *(void**)&LINK_getCameraInfo =
+ ::dlsym(libcameraHandle, "HAL_getCameraInfo");
+ LINK_getCameraInfo(camera_id, info);
+ dynamic = true;
+ }
+ dlclose(libcameraHandle);
+ }
+ if (!dynamic) {
+ info->facing = CAMERA_FACING_BACK;
+ info->orientation = 90;
+ }
return NO_ERROR;
}
@@ -593,7 +714,7 @@ qcamera_send_command(struct camera_device * device, int32_t cmd,
{
LOGV("qcamera_send_command: cmd:%d arg0:%d arg1:%d\n",
cmd, arg0, arg1);
- return NO_ERROR;
+ return qCamera->sendCommand(cmd, arg0, arg1);
}
void
@@ -631,17 +752,40 @@ camera_device_close(hw_device_t* device)
return rc;
}
+
int
qcamera_device_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
+ void *libcameraHandle;
int cameraId = atoi(name);
LOGD("qcamera_device_open: name:%s device:%p cameraId:%d\n",
name, device, cameraId);
- qCamera = openCameraHardware(cameraId);
+ libcameraHandle = ::dlopen("libcamera.so", RTLD_NOW);
+ LOGD("loading libcamera at %p", libcameraHandle);
+ if (!libcameraHandle) {
+ LOGE("FATAL ERROR: could not dlopen libcamera.so: %s", dlerror());
+ return false;
+ }
+
+ if (::dlsym(libcameraHandle, "openCameraHardware") != NULL) {
+ *(void**)&LINK_openCameraHardware =
+ ::dlsym(libcameraHandle, "openCameraHardware");
+ } else if (::dlsym(libcameraHandle, "HAL_openCameraHardware") != NULL) {
+ *(void**)&LINK_openCameraHardware =
+ ::dlsym(libcameraHandle, "HAL_openCameraHardware");
+ } else {
+ LOGE("FATAL ERROR: Could not find openCameraHardware");
+ dlclose(libcameraHandle);
+ return false;
+ }
+
+ qCamera = LINK_openCameraHardware(cameraId);
+ ::dlclose(libcameraHandle);
+
camera_device_t* camera_device = NULL;
camera_device_ops_t* camera_ops = NULL;
813 cameraHal.cpp.orig
View
@@ -0,0 +1,813 @@
+/*
+ * Copyright (C) 2012, Raviprasad V Mummidi.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CameraHAL"
+
+#include <CameraHardwareInterface.h>
+#include <hardware/hardware.h>
+#include <hardware/camera.h>
+#include <binder/IMemory.h>
+#include <fcntl.h>
+#include <linux/ioctl.h>
+#include <linux/msm_mdp.h>
+#include <gralloc_priv.h>
+#include <ui/Rect.h>
+#include <ui/GraphicBufferMapper.h>
+#include <dlfcn.h>
+
+#define NO_ERROR 0
+#define GRALLOC_USAGE_PMEM_PRIVATE_ADSP GRALLOC_USAGE_PRIVATE_0
+//#define MSM_COPY_HW 1
+
+//#define LOGV LOGI
+
+struct qcom_mdp_rect {
+ uint32_t x;
+ uint32_t y;
+ uint32_t w;
+ uint32_t h;
+};
+
+struct qcom_mdp_img {
+ uint32_t width;
+ int32_t height;
+ int32_t format;
+ int32_t offset;
+ int memory_id; /* The file descriptor */
+};
+
+struct qcom_mdp_blit_req {
+ struct qcom_mdp_img src;
+ struct qcom_mdp_img dst;
+ struct qcom_mdp_rect src_rect;
+ struct qcom_mdp_rect dst_rect;
+ uint32_t alpha;
+ uint32_t transp_mask;
+ uint32_t flags;
+};
+
+struct blitreq {
+ unsigned int count;
+ struct qcom_mdp_blit_req req;
+};
+
+/* Prototypes and extern functions. */
+//extern "C" android::sp<android::CameraHardwareInterface> openCameraHardware(int id);
+android::sp<android::CameraHardwareInterface> (*LINK_openCameraHardware)(int id);
+int (*LINK_getNumberofCameras)(void);
+void (*LINK_getCameraInfo)(int cameraId, struct camera_info *info);
+int qcamera_device_open(const hw_module_t* module, const char* name,
+ hw_device_t** device);
+int CameraHAL_GetNum_Cameras(void);
+int CameraHAL_GetCam_Info(int camera_id, struct camera_info *info);
+
+/* Global variables. */
+camera_notify_callback origNotify_cb = NULL;
+camera_data_callback origData_cb = NULL;
+camera_data_timestamp_callback origDataTS_cb = NULL;
+camera_request_memory origCamReqMemory = NULL;
+
+android::String8 g_str;
+android::CameraParameters camSettings;
+preview_stream_ops_t *mWindow = NULL;
+android::sp<android::CameraHardwareInterface> qCamera;
+
+static hw_module_methods_t camera_module_methods = {
+ open: qcamera_device_open
+};
+
+camera_module_t HAL_MODULE_INFO_SYM = {
+ common: {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: CAMERA_HARDWARE_MODULE_ID,
+ name: "Camera HAL for ICS",
+ author: "Raviprasad V Mummidi",
+ methods: &camera_module_methods,
+ dso: NULL,
+ reserved: {0},
+ },
+ get_number_of_cameras: CameraHAL_GetNum_Cameras,
+ get_camera_info: CameraHAL_GetCam_Info,
+};
+
+/* HAL helper functions. */
+void
+CameraHAL_NotifyCb(int32_t msg_type, int32_t ext1,
+ int32_t ext2, void *user)
+{
+ LOGV("CameraHAL_NotifyCb: msg_type:%d ext1:%d ext2:%d user:%p\n",
+ msg_type, ext1, ext2, user);
+ if (origNotify_cb != NULL) {
+ origNotify_cb(msg_type, ext1, ext2, user);
+ }
+}
+
+bool
+CameraHAL_CopyBuffers_Hw(int srcFd, int destFd,
+ size_t srcOffset, size_t destOffset,
+ int srcFormat, int destFormat,
+ int x, int y, int w, int h)
+{
+ struct blitreq blit;
+ bool success = true;
+ int fb_fd = open("/dev/graphics/fb0", O_RDWR);
+
+#ifndef MSM_COPY_HW
+ return false;
+#endif
+
+ if (fb_fd < 0) {
+ LOGD("CameraHAL_CopyBuffers_Hw: Error opening /dev/graphics/fb0\n");
+ return false;
+ }
+
+ LOGV("CameraHAL_CopyBuffers_Hw: srcFD:%d destFD:%d srcOffset:%#x"
+ " destOffset:%#x x:%d y:%d w:%d h:%d\n", srcFd, destFd, srcOffset,
+ destOffset, x, y, w, h);
+
+ memset(&blit, 0, sizeof(blit));
+ blit.count = 1;
+
+ blit.req.flags = 0;
+ blit.req.alpha = 0xff;
+ blit.req.transp_mask = 0xffffffff;
+
+ blit.req.src.width = w;
+ blit.req.src.height = h;
+ blit.req.src.offset = srcOffset;
+ blit.req.src.memory_id = srcFd;
+ blit.req.src.format = srcFormat;
+
+ blit.req.dst.width = w;
+ blit.req.dst.height = h;
+ blit.req.dst.offset = destOffset;
+ blit.req.dst.memory_id = destFd;
+ blit.req.dst.format = destFormat;
+
+ blit.req.src_rect.x = blit.req.dst_rect.x = x;
+ blit.req.src_rect.y = blit.req.dst_rect.y = y;
+ blit.req.src_rect.w = blit.req.dst_rect.w = w;
+ blit.req.src_rect.h = blit.req.dst_rect.h = h;
+
+ if (ioctl(fb_fd, MSMFB_BLIT, &blit)) {
+ LOGV("CameraHAL_CopyBuffers_Hw: MSMFB_BLIT failed = %d %s\n",
+ errno, strerror(errno));
+ success = false;
+ }
+ close(fb_fd);
+ return success;
+}
+
+void
+CameraHal_Decode_Sw(unsigned int* rgb, char* yuv420sp, int width, int height)
+{
+ int frameSize = width * height;
+
+ if (!qCamera->previewEnabled()) return;
+
+ for (int j = 0, yp = 0; j < height; j++) {
+ int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
+ for (int i = 0; i < width; i++, yp++) {
+ int y = (0xff & ((int) yuv420sp[yp])) - 16;
+ if (y < 0) y = 0;
+ if ((i & 1) == 0) {
+ v = (0xff & yuv420sp[uvp++]) - 128;
+ u = (0xff & yuv420sp[uvp++]) - 128;
+ }
+
+ int y1192 = 1192 * y;
+ int r = (y1192 + 1634 * v);
+ int g = (y1192 - 833 * v - 400 * u);
+ int b = (y1192 + 2066 * u);
+
+ if (r < 0) r = 0; else if (r > 262143) r = 262143;
+ if (g < 0) g = 0; else if (g > 262143) g = 262143;
+ if (b < 0) b = 0; else if (b > 262143) b = 262143;
+
+ rgb[yp] = 0xff000000 | ((b << 6) & 0xff0000) |
+ ((g >> 2) & 0xff00) | ((r >> 10) & 0xff);
+ }
+ }
+}
+
+
+
+void
+CameraHAL_CopyBuffers_Sw(char *dest, char *src, int size)
+{
+ int i;
+ int numWords = size / sizeof(unsigned);
+ unsigned *srcWords = (unsigned *)src;
+ unsigned *destWords = (unsigned *)dest;
+
+ for (i = 0; i < numWords; i++) {
+ if ((i % 8) == 0 && (i + 8) < numWords) {
+ __builtin_prefetch(srcWords + 8, 0, 0);
+ __builtin_prefetch(destWords + 8, 1, 0);
+ }
+ *destWords++ = *srcWords++;
+ }
+ if (__builtin_expect((size - (numWords * sizeof(unsigned))) > 0, 0)) {
+ int numBytes = size - (numWords * sizeof(unsigned));
+ char *destBytes = (char *)destWords;
+ char *srcBytes = (char *)srcWords;
+ for (i = 0; i < numBytes; i++) {
+ *destBytes++ = *srcBytes++;
+ }
+ }
+}
+
+void
+CameraHAL_HandlePreviewData(const android::sp<android::IMemory>& dataPtr,
+ preview_stream_ops_t *mWindow,
+ camera_request_memory getMemory,
+ int32_t previewWidth, int32_t previewHeight)
+{
+ if (mWindow != NULL && getMemory != NULL) {
+ ssize_t offset;
+ size_t size;
+ int32_t previewFormat = MDP_Y_CBCR_H2V2;
+ int32_t destFormat = MDP_RGBA_8888;
+
+ android::status_t retVal;
+ android::sp<android::IMemoryHeap> mHeap = dataPtr->getMemory(&offset,
+ &size);
+
+ LOGV("CameraHAL_HandlePreviewData: previewWidth:%d previewHeight:%d "
+ "offset:%#x size:%#x base:%p\n", previewWidth, previewHeight,
+ (unsigned)offset, size, mHeap != NULL ? mHeap->base() : 0);
+
+ mWindow->set_usage(mWindow,
+ GRALLOC_USAGE_PMEM_PRIVATE_ADSP |
+ GRALLOC_USAGE_SW_READ_OFTEN);
+ retVal = mWindow->set_buffers_geometry(mWindow,
+ previewWidth, previewHeight,
+ HAL_PIXEL_FORMAT_RGBA_8888);
+ if (retVal == NO_ERROR) {
+ int32_t stride;
+ buffer_handle_t *bufHandle = NULL;
+
+ LOGV("CameraHAL_HandlePreviewData: dequeueing buffer\n");
+ retVal = mWindow->dequeue_buffer(mWindow, &bufHandle, &stride);
+ if (retVal == NO_ERROR) {
+ retVal = mWindow->lock_buffer(mWindow, bufHandle);
+ if (retVal == NO_ERROR) {
+ private_handle_t const *privHandle =
+ reinterpret_cast<private_handle_t const *>(*bufHandle);
+ if (!CameraHAL_CopyBuffers_Hw(mHeap->getHeapID(), privHandle->fd,
+ offset, privHandle->offset,
+ previewFormat, destFormat,
+ 0, 0, previewWidth,
+ previewHeight)) {
+ void *bits;
+ android::Rect bounds;
+ android::GraphicBufferMapper &mapper =
+ android::GraphicBufferMapper::get();
+
+ bounds.left = 0;
+ bounds.top = 0;
+ bounds.right = previewWidth;
+ bounds.bottom = previewHeight;
+
+ mapper.lock(*bufHandle, GRALLOC_USAGE_SW_READ_OFTEN, bounds,
+ &bits);
+ LOGV("CameraHAL_HPD: w:%d h:%d bits:%p",
+ previewWidth, previewHeight, bits);
+ CameraHal_Decode_Sw((unsigned int *)bits, (char *)mHeap->base() + offset,
+ previewWidth, previewHeight);
+
+ // unlock buffer before sending to display
+ mapper.unlock(*bufHandle);
+ }
+
+ mWindow->enqueue_buffer(mWindow, bufHandle);
+ LOGV("CameraHAL_HandlePreviewData: enqueued buffer\n");
+ } else {
+ LOGE("CameraHAL_HandlePreviewData: ERROR locking the buffer\n");
+ mWindow->cancel_buffer(mWindow, bufHandle);
+ }
+ } else {
+ LOGE("CameraHAL_HandlePreviewData: ERROR dequeueing the buffer\n");
+ }
+ }
+ }
+}
+
+camera_memory_t *
+CameraHAL_GenClientData(const android::sp<android::IMemory> &dataPtr,
+ camera_request_memory reqClientMemory,
+ void *user)
+{
+ ssize_t offset;
+ size_t size;
+ camera_memory_t *clientData = NULL;
+ android::sp<android::IMemoryHeap> mHeap = dataPtr->getMemory(&offset, &size);
+
+ LOGV("CameraHAL_GenClientData: offset:%#x size:%#x base:%p\n",
+ (unsigned)offset, size, mHeap != NULL ? mHeap->base() : 0);
+
+ clientData = reqClientMemory(-1, size, 1, user);
+ if (clientData != NULL) {
+ CameraHAL_CopyBuffers_Sw((char *)clientData->data,
+ (char *)(mHeap->base()) + offset, size);
+ } else {
+ LOGV("CameraHAL_GenClientData: ERROR allocating memory from client\n");
+ }
+ return clientData;
+}
+
+void
+CameraHAL_DataCb(int32_t msg_type, const android::sp<android::IMemory>& dataPtr,
+ void *user)
+{
+ LOGV("CameraHAL_DataCb: msg_type:%d user:%p\n", msg_type, user);
+ if (msg_type == CAMERA_MSG_PREVIEW_FRAME) {
+ int32_t previewWidth, previewHeight;
+ android::CameraParameters hwParameters = qCamera->getParameters();
+ hwParameters.getPreviewSize(&previewWidth, &previewHeight);
+ CameraHAL_HandlePreviewData(dataPtr, mWindow, origCamReqMemory,
+ previewWidth, previewHeight);
+ }
+
+ if (origData_cb != NULL && origCamReqMemory != NULL) {
+ camera_memory_t *clientData = CameraHAL_GenClientData(dataPtr,
+ origCamReqMemory, user);
+ if (clientData != NULL) {
+ LOGV("CameraHAL_DataCb: Posting data to client\n");
+ origData_cb(msg_type, clientData, 0, NULL, user);
+ }
+ }
+}
+
+void
+CameraHAL_DataTSCb(nsecs_t timestamp, int32_t msg_type,
+ const android::sp<android::IMemory>& dataPtr, void *user)
+{
+ LOGV("CameraHAL_DataTSCb: timestamp:%lld msg_type:%d user:%p\n",
+ timestamp /1000, msg_type, user);
+
+ if (origDataTS_cb != NULL && origCamReqMemory != NULL) {
+ camera_memory_t *clientData = CameraHAL_GenClientData(dataPtr,
+ origCamReqMemory, user);
+ if (clientData != NULL) {
+ LOGV("CameraHAL_DataTSCb: Posting data to client timestamp:%lld\n",
+ systemTime());
+ origDataTS_cb(timestamp, msg_type, clientData, 0, user);
+ qCamera->releaseRecordingFrame(dataPtr);
+ } else {
+ LOGD("CameraHAL_DataTSCb: ERROR allocating memory from client\n");
+ }
+ }
+}
+
+int
+CameraHAL_GetNum_Cameras(void)
+{
+ int numCameras = 1;
+
+ LOGE("CameraHAL_GetNum_Cameras:\n");
+ void *libcameraHandle = ::dlopen("libcamera.so", RTLD_NOW);
+ LOGD("CameraHAL_GetNum_Cameras: loading libcamera at %p", libcameraHandle);
+ if (!libcameraHandle) {
+ LOGE("FATAL ERROR: could not dlopen libcamera.so: %s", dlerror());
+ } else {
+ if (::dlsym(libcameraHandle, "HAL_getNumberOfCameras") != NULL) {
+ *(void**)&LINK_getNumberofCameras =
+ ::dlsym(libcameraHandle, "HAL_getNumberOfCameras");
+ numCameras = LINK_getNumberofCameras();
+ LOGD("CameraHAL_GetNum_Cameras: numCameras:%d", numCameras);
+ }
+ dlclose(libcameraHandle);
+ }
+ return numCameras;
+}
+
+int
+CameraHAL_GetCam_Info(int camera_id, struct camera_info *info)
+{
+ bool dynamic = false;
+ LOGV("CameraHAL_GetCam_Info:\n");
+ void *libcameraHandle = ::dlopen("libcamera.so", RTLD_NOW);
+ LOGD("CameraHAL_GetNum_Cameras: loading libcamera at %p", libcameraHandle);
+ if (!libcameraHandle) {
+ LOGE("FATAL ERROR: could not dlopen libcamera.so: %s", dlerror());
+ return EINVAL;
+ } else {
+ if (::dlsym(libcameraHandle, "HAL_getCameraInfo") != NULL) {
+ *(void**)&LINK_getCameraInfo =
+ ::dlsym(libcameraHandle, "HAL_getCameraInfo");
+ LINK_getCameraInfo(camera_id, info);
+ dynamic = true;
+ }
+ dlclose(libcameraHandle);
+ }
+ if (!dynamic) {
+ info->facing = CAMERA_FACING_BACK;
+ info->orientation = 90;
+ }
+ return NO_ERROR;
+}
+
+void
+CameraHAL_FixupParams(android::CameraParameters &settings)
+{
+ const char *preview_sizes =
+ "1280x720,800x480,768x432,720x480,640x480,576x432,480x320,384x288,352x288,320x240,240x160,176x144";
+ const char *video_sizes =
+ "1280x720,800x480,720x480,640x480,352x288,320x240,176x144";
+ const char *preferred_size = "640x480";
+ const char *preview_frame_rates = "30,27,24,15";
+ const char *preferred_frame_rate = "15";
+ const char *frame_rate_range = "(15,30)";
+
+ settings.set(android::CameraParameters::KEY_VIDEO_FRAME_FORMAT,
+ android::CameraParameters::PIXEL_FORMAT_YUV420SP);
+
+ if (!settings.get(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES)) {
+ settings.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
+ preview_sizes);
+ }
+
+ if (!settings.get(android::CameraParameters::KEY_SUPPORTED_VIDEO_SIZES)) {
+ settings.set(android::CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
+ video_sizes);
+ }
+
+ if (!settings.get(android::CameraParameters::KEY_VIDEO_SIZE)) {
+ settings.set(android::CameraParameters::KEY_VIDEO_SIZE, preferred_size);
+ }
+
+ if (!settings.get(android::CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO)) {
+ settings.set(android::CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO,
+ preferred_size);
+ }
+
+ if (!settings.get(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES)) {
+ settings.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
+ preview_frame_rates);
+ }
+
+ if (!settings.get(android::CameraParameters::KEY_PREVIEW_FRAME_RATE)) {
+ settings.set(android::CameraParameters::KEY_PREVIEW_FRAME_RATE,
+ preferred_frame_rate);
+ }
+
+ if (!settings.get(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE)) {
+ LOGD("Setting KEY_PREVIEW_FPS_RANGE: %s\n", frame_rate_range);
+ settings.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE,
+ frame_rate_range);
+ }
+}
+
+/* Hardware Camera interface handlers. */
+int
+qcamera_set_preview_window(struct camera_device * device,
+ struct preview_stream_ops *window)
+{
+ LOGV("qcamera_set_preview_window : Window :%p\n", window);
+ if (device == NULL) {
+ LOGE("qcamera_set_preview_window : Invalid device.\n");
+ return -EINVAL;
+ } else {
+ LOGV("qcamera_set_preview_window : window :%p\n", window);
+ mWindow = window;
+ return 0;
+ }
+}
+
+void
+qcamera_set_callbacks(struct camera_device * device,
+ camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory, void *user)
+{
+ LOGV("qcamera_set_callbacks: notify_cb: %p, data_cb: %p "
+ "data_cb_timestamp: %p, get_memory: %p, user :%p",
+ notify_cb, data_cb, data_cb_timestamp, get_memory, user);
+
+ origNotify_cb = notify_cb;
+ origData_cb = data_cb;
+ origDataTS_cb = data_cb_timestamp;
+ origCamReqMemory = get_memory;
+ qCamera->setCallbacks(CameraHAL_NotifyCb, CameraHAL_DataCb,
+ CameraHAL_DataTSCb, user);
+}
+
+void
+qcamera_enable_msg_type(struct camera_device * device, int32_t msg_type)
+{
+ LOGV("qcamera_enable_msg_type: msg_type:%#x\n", msg_type);
+ if (msg_type == 0xfff) {
+ msg_type = 0x1ff;
+ } else {
+ msg_type &= ~(CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_RAW_IMAGE_NOTIFY);
+ }
+ qCamera->enableMsgType(msg_type);
+}
+
+void
+qcamera_disable_msg_type(struct camera_device * device, int32_t msg_type)
+{
+ LOGV("qcamera_disable_msg_type: msg_type:%#x\n", msg_type);
+ if (msg_type == 0xfff) {
+ msg_type = 0x1ff;
+ }
+ qCamera->disableMsgType(msg_type);
+}
+
+int
+qcamera_msg_type_enabled(struct camera_device * device, int32_t msg_type)
+{
+ LOGV("qcamera_msg_type_enabled: msg_type:%d\n", msg_type);
+ return qCamera->msgTypeEnabled(msg_type);
+}
+
+int
+qcamera_start_preview(struct camera_device * device)
+{
+ LOGV("qcamera_start_preview: Enabling CAMERA_MSG_PREVIEW_FRAME\n");
+
+ /* TODO: Remove hack. */
+ LOGV("qcamera_start_preview: Preview enabled:%d msg enabled:%d\n",
+ qCamera->previewEnabled(),
+ qCamera->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME));
+ if (!qCamera->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) {
+ qCamera->enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+ }
+ return qCamera->startPreview();
+}
+
+void
+qcamera_stop_preview(struct camera_device * device)
+{
+ LOGV("qcamera_stop_preview: msgenabled:%d\n",
+ qCamera->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME));
+
+ /* TODO: Remove hack. */
+ if (qCamera->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) {
+ qCamera->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+ }
+ return qCamera->stopPreview();
+}
+
+int
+qcamera_preview_enabled(struct camera_device * device)
+{
+ LOGV("qcamera_preview_enabled:\n");
+ return qCamera->previewEnabled() ? 1 : 0;
+}
+
+int
+qcamera_store_meta_data_in_buffers(struct camera_device * device, int enable)
+{
+ LOGV("qcamera_store_meta_data_in_buffers:\n");
+ return NO_ERROR;
+}
+
+int
+qcamera_start_recording(struct camera_device * device)
+{
+ LOGV("qcamera_start_recording\n");
+
+ /* TODO: Remove hack. */
+ qCamera->enableMsgType(CAMERA_MSG_VIDEO_FRAME);
+ qCamera->startRecording();
+ return NO_ERROR;
+}
+
+void
+qcamera_stop_recording(struct camera_device * device)
+{
+ LOGV("qcamera_stop_recording:\n");
+
+ /* TODO: Remove hack. */
+ qCamera->disableMsgType(CAMERA_MSG_VIDEO_FRAME);
+ qCamera->stopRecording();
+}
+
+int
+qcamera_recording_enabled(struct camera_device * device)
+{
+ LOGV("qcamera_recording_enabled:\n");
+ return (int)qCamera->recordingEnabled();
+}
+
+void
+qcamera_release_recording_frame(struct camera_device * device,
+ const void *opaque)
+{
+ /*
+ * We release the frame immediately in CameraHAL_DataTSCb after making a
+ * copy. So, this is just a NOP.
+ */
+ LOGV("qcamera_release_recording_frame: opaque:%p\n", opaque);
+}
+
+int
+qcamera_auto_focus(struct camera_device * device)
+{
+ LOGV("qcamera_auto_focus:\n");
+ qCamera->autoFocus();
+ return NO_ERROR;
+}
+
+int
+qcamera_cancel_auto_focus(struct camera_device * device)
+{
+ LOGV("qcamera_cancel_auto_focus:\n");
+ qCamera->cancelAutoFocus();
+ return NO_ERROR;
+}
+
+int
+qcamera_take_picture(struct camera_device * device)
+{
+ LOGV("qcamera_take_picture:\n");
+
+ /* TODO: Remove hack. */
+ qCamera->enableMsgType(CAMERA_MSG_SHUTTER |
+ CAMERA_MSG_POSTVIEW_FRAME |
+ CAMERA_MSG_RAW_IMAGE |
+ CAMERA_MSG_COMPRESSED_IMAGE);
+
+ qCamera->takePicture();
+ return NO_ERROR;
+}
+
+int
+qcamera_cancel_picture(struct camera_device * device)
+{
+ LOGV("camera_cancel_picture:\n");
+ qCamera->cancelPicture();
+ return NO_ERROR;
+}
+
+int
+qcamera_set_parameters(struct camera_device * device, const char *params)
+{
+ LOGV("qcamera_set_parameters: %s\n", params);
+ g_str = android::String8(params);
+ camSettings.unflatten(g_str);
+ qCamera->setParameters(camSettings);
+ return NO_ERROR;
+}
+
+char*
+qcamera_get_parameters(struct camera_device * device)
+{
+ char *rc = NULL;
+ LOGV("qcamera_get_parameters\n");
+ camSettings = qCamera->getParameters();
+ LOGV("qcamera_get_parameters: after calling qCamera->getParameters()\n");
+ CameraHAL_FixupParams(camSettings);
+ g_str = camSettings.flatten();
+ rc = strdup((char *)g_str.string());
+ LOGV("camera_get_parameters: returning rc:%p :%s\n",
+ rc, (rc != NULL) ? rc : "EMPTY STRING");
+ return rc;
+}
+
+void
+qcamera_put_parameters(struct camera_device *device, char *params)
+{
+ LOGV("qcamera_put_parameters: params:%p %s", params, params);
+ free(params);
+}
+
+
+int
+qcamera_send_command(struct camera_device * device, int32_t cmd,
+ int32_t arg0, int32_t arg1)
+{
+ LOGV("qcamera_send_command: cmd:%d arg0:%d arg1:%d\n",
+ cmd, arg0, arg1);
+ return qCamera->sendCommand(cmd, arg0, arg1);
+}
+
+void
+qcamera_release(struct camera_device * device)
+{
+ LOGV("camera_release:\n");
+ qCamera->release();
+}
+
+int
+qcamera_dump(struct camera_device * device, int fd)
+{
+ LOGV("qcamera_dump:\n");
+ android::Vector<android::String16> args;
+ return qCamera->dump(fd, args);
+}
+
+int
+camera_device_close(hw_device_t* device)
+{
+ int rc = -EINVAL;
+ LOGD("camera_device_close\n");
+ camera_device_t *cameraDev = (camera_device_t *)device;
+ if (cameraDev) {
+ camera_device_ops_t *camera_ops = cameraDev->ops;
+ if (camera_ops) {
+ if (qCamera != NULL) {
+ qCamera.clear();
+ }
+ free(camera_ops);
+ }
+ free(cameraDev);
+ rc = NO_ERROR;
+ }
+ return rc;
+}
+
+
+int
+qcamera_device_open(const hw_module_t* module, const char* name,
+ hw_device_t** device)
+{
+
+ void *libcameraHandle;
+ int cameraId = atoi(name);
+
+ LOGD("qcamera_device_open: name:%s device:%p cameraId:%d\n",
+ name, device, cameraId);
+
+ libcameraHandle = ::dlopen("libcamera.so", RTLD_NOW);
+ LOGD("loading libcamera at %p", libcameraHandle);
+ if (!libcameraHandle) {
+ LOGE("FATAL ERROR: could not dlopen libcamera.so: %s", dlerror());
+ return false;
+ }
+
+ if (::dlsym(libcameraHandle, "openCameraHardware") != NULL) {
+ *(void**)&LINK_openCameraHardware =
+ ::dlsym(libcameraHandle, "openCameraHardware");
+ } else if (::dlsym(libcameraHandle, "HAL_openCameraHardware") != NULL) {
+ *(void**)&LINK_openCameraHardware =
+ ::dlsym(libcameraHandle, "HAL_openCameraHardware");
+ } else {
+ LOGE("FATAL ERROR: Could not find openCameraHardware");
+ dlclose(libcameraHandle);
+ return false;
+ }
+
+ qCamera = LINK_openCameraHardware(cameraId);
+ ::dlclose(libcameraHandle);
+
+ camera_device_t* camera_device = NULL;
+ camera_device_ops_t* camera_ops = NULL;
+
+ camera_device = (camera_device_t*)malloc(sizeof(*camera_device));
+ camera_ops = (camera_device_ops_t*)malloc(sizeof(*camera_ops));
+ memset(camera_device, 0, sizeof(*camera_device));
+ memset(camera_ops, 0, sizeof(*camera_ops));
+
+ camera_device->common.tag = HARDWARE_DEVICE_TAG;
+ camera_device->common.version = 0;
+ camera_device->common.module = (hw_module_t *)(module);
+ camera_device->common.close = camera_device_close;
+ camera_device->ops = camera_ops;
+
+ camera_ops->set_preview_window = qcamera_set_preview_window;
+ camera_ops->set_callbacks = qcamera_set_callbacks;
+ camera_ops->enable_msg_type = qcamera_enable_msg_type;
+ camera_ops->disable_msg_type = qcamera_disable_msg_type;
+ camera_ops->msg_type_enabled = qcamera_msg_type_enabled;
+ camera_ops->start_preview = qcamera_start_preview;
+ camera_ops->stop_preview = qcamera_stop_preview;
+ camera_ops->preview_enabled = qcamera_preview_enabled;
+ camera_ops->store_meta_data_in_buffers = qcamera_store_meta_data_in_buffers;
+ camera_ops->start_recording = qcamera_start_recording;
+ camera_ops->stop_recording = qcamera_stop_recording;
+ camera_ops->recording_enabled = qcamera_recording_enabled;
+ camera_ops->release_recording_frame = qcamera_release_recording_frame;
+ camera_ops->auto_focus = qcamera_auto_focus;
+ camera_ops->cancel_auto_focus = qcamera_cancel_auto_focus;
+ camera_ops->take_picture = qcamera_take_picture;
+ camera_ops->cancel_picture = qcamera_cancel_picture;
+
+ camera_ops->set_parameters = qcamera_set_parameters;
+ camera_ops->get_parameters = qcamera_get_parameters;
+ camera_ops->put_parameters = qcamera_put_parameters;
+ camera_ops->send_command = qcamera_send_command;
+ camera_ops->release = qcamera_release;
+ camera_ops->dump = qcamera_dump;
+
+ *device = &camera_device->common;
+ return NO_ERROR;
+}
Please sign in to comment.
Something went wrong with that request. Please try again.