From 5b08cc9343f6d14b6b5c9a943de38632fb78c805 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Thu, 30 Apr 2009 12:19:03 -0700 Subject: [PATCH 02/29] Add new implementation of libcamera (as libcamera2) (disabled) libcamera2 uses code under vendor/qcom/proprietary/mm-camera, which is the (Qualcomm proprietary) user-space component of the new camera framework. Signed-off-by: Iliyan Malchev --- libcamera2/Android.mk | 35 + libcamera2/QualcommCameraHardware.cpp | 2136 +++++++++++++++++++++++++ libcamera2/QualcommCameraHardware.h | 286 ++++ 3 files changed, 2457 insertions(+) create mode 100755 libcamera2/Android.mk create mode 100755 libcamera2/QualcommCameraHardware.cpp create mode 100755 libcamera2/QualcommCameraHardware.h diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk new file mode 100755 index 0000000..dab1c17 --- /dev/null +++ b/libcamera2/Android.mk @@ -0,0 +1,35 @@ +BUILD_LIBCAMERA:= +ifeq ($(BUILD_LIBCAMERA),true) + +# When zero we link against libmmcamera; when 1, we dlopen libmmcamera. +DLOPEN_LIBMMCAMERA:=1 + +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= QualcommCameraHardware.cpp + +LOCAL_CFLAGS:= -DDLOPEN_LIBMMCAMERA=$(DLOPEN_LIBMMCAMERA) + +LOCAL_C_INCLUDES+= \ + vendor/qcom/proprietary/mm-camera/common \ + vendor/qcom/proprietary/mm-camera/apps/appslib \ + vendor/qcom/proprietary/mm-camera/jpeg \ + vendor/qcom/proprietary/mm-camera/jpeg/inc + +LOCAL_SHARED_LIBRARIES:= libutils libui liblog + +ifneq ($(DLOPEN_LIBMMCAMERA),1) +LOCAL_SHARED_LIBRARIES+= libmmcamera +else +LOCAL_SHARED_LIBRARIES+= libdl +endif + +LOCAL_MODULE:= libcamera +include $(BUILD_SHARED_LIBRARY) + +endif # BUILD_TINY_ANDROID +endif # BUILD_LIBCAMERA diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp new file mode 100755 index 0000000..2209c8e --- /dev/null +++ b/libcamera2/QualcommCameraHardware.cpp @@ -0,0 +1,2136 @@ +/* +** Copyright 2008, Google Inc. +** +** 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_NDEBUG 0 +#define LOG_TAG "QualcommCameraHardware" +#include + +#include "QualcommCameraHardware.h" + +#include +#include +#include +#include +#include +#include +#if HAVE_ANDROID_OS +#include +#endif +#include + +#define CAPTURE_RAW 0 +#define LIKELY(exp) __builtin_expect(!!(exp), 1) +#define UNLIKELY(exp) __builtin_expect(!!(exp), 0) + +extern "C" { + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#define THUMBNAIL_WIDTH 512 +#define THUMBNAIL_HEIGHT 384 +#define THUMBNAIL_WIDTH_STR "512" +#define THUMBNAIL_HEIGHT_STR "384" +#define DEFAULT_PICTURE_WIDTH 2048 // 1280 +#define DEFAULT_PICTURE_HEIGHT 1536 // 768 +#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2) + +#define DEFAULT_PREVIEW_SETTING 2 // HVGA +#define MAX_ZOOM_STEPS 6 +#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(preview_size_type)) + +#define BRIGHTNESS_MAX 10 // FIXME: this should correlate with brightness-values +#define ZOOM_MAX 10 // FIXME: this should correlate with zoom-values + +#if DLOPEN_LIBMMCAMERA +#include + +void* (*LINK_cam_conf)(void *data); +void* (*LINK_cam_frame)(void *data); +bool (*LINK_jpeg_encoder_init)(); +void (*LINK_jpeg_encoder_join)(); +bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen, + const uint8_t *thumbnailbuf, int thumbnailfd, + const uint8_t *snapshotbuf, int snapshotfd); +int (*LINK_camframe_terminate)(void); +int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); +// callbacks +void (**LINK_mmcamera_camframe_callback)(struct msm_frame_t *frame); +void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, + uint32_t buff_size); +void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); +#else +#define LINK_cam_conf cam_conf +#define LINK_cam_frame cam_frame +#define LINK_jpeg_encoder_init jpeg_encoder_init +#define LINK_jpeg_encoder_join jpeg_encoder_join +#define LINK_jpeg_encoder_encode jpeg_encoder_encode +#define LINK_camframe_terminate camframe_terminate +#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality +extern void (*mmcamera_camframe_callback)(struct msm_frame_t *frame); +extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, + uint32_t buff_size); +extern void (*mmcamera_jpeg_callback)(jpeg_event_t status); +#endif + +} // extern "C" + +struct preview_size_type { + int width; + int height; +}; + +static preview_size_type preview_sizes[] = { + { 800, 480 }, // WVGA + { 640, 480 }, // VGA + { 480, 320 }, // HVGA + { 352, 288 }, // CIF + { 320, 240 }, // QVGA + { 176, 144 }, // QCIF +}; + +struct str_map { + const char *const desc; + int val; +}; + +static int attr_lookup(const struct str_map *const arr, + const char *name, + int def) +{ + if (name) { + const struct str_map *trav = arr; + while (trav->desc) { + if (!strcmp(trav->desc, name)) + return trav->val; + trav++; + } + } + return def; +} + +#define INIT_VALUES_FOR(parm) do { \ + if (!parm##_values) { \ + parm##_values = (char *)malloc(sizeof(parm)/ \ + sizeof(parm[0])*30); \ + char *ptr = parm##_values; \ + const str_map *trav; \ + for (trav = parm; trav->desc; trav++) { \ + int len = strlen(trav->desc); \ + strcpy(ptr, trav->desc); \ + ptr += len; \ + *ptr++ = ','; \ + } \ + *--ptr = 0; \ + } \ +} while(0) + +// from aeecamera.h +static const str_map whitebalance[] = { + { "auto", CAMERA_WB_AUTO }, + { "custom", CAMERA_WB_CUSTOM }, + { "incandescent", CAMERA_WB_INCANDESCENT }, + { "florescent", CAMERA_WB_FLUORESCENT }, + { "daylight", CAMERA_WB_DAYLIGHT }, + { "cloudy", CAMERA_WB_CLOUDY_DAYLIGHT }, + { "twilight", CAMERA_WB_TWILIGHT }, + { "shade", CAMERA_WB_SHADE }, + { NULL, 0 } +}; +static char *whitebalance_values; + +// from camera_effect_t +static const str_map color_effects[] = { + { "none", CAMERA_EFFECT_OFF }, /* This list must match aeecamera.h */ + { "mono", CAMERA_EFFECT_MONO }, + { "negative", CAMERA_EFFECT_NEGATIVE }, + { "solarize", CAMERA_EFFECT_SOLARIZE }, + { "pastel", CAMERA_EFFECT_PASTEL }, + { "mosaic", CAMERA_EFFECT_MOSAIC }, + { "resize", CAMERA_EFFECT_RESIZE }, + { "sepia", CAMERA_EFFECT_SEPIA }, + { "postersize", CAMERA_EFFECT_POSTERIZE }, + { "whiteboard", CAMERA_EFFECT_WHITEBOARD }, + { "blackboard", CAMERA_EFFECT_BLACKBOARD }, + { "aqua", CAMERA_EFFECT_AQUA }, + { NULL, 0 } +}; +static char *color_effects_values; + +// from qcamera/common/camera.h +static const str_map anti_banding[] = { + { "off", CAMERA_ANTIBANDING_OFF }, + { "60hz", CAMERA_ANTIBANDING_60HZ }, + { "50hz", CAMERA_ANTIBANDING_50HZ }, + { "auto", CAMERA_ANTIBANDING_AUTO }, + { NULL, 0 } +}; +static char *anti_banding_values; + +// round to the next power of two +static inline unsigned clp2(unsigned x) +{ + x = x - 1; + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >>16); + return x + 1; +} + +namespace android { + +static Mutex singleton_lock; + +static void receive_camframe_callback(struct msm_frame_t *frame); +static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size); +static void receive_jpeg_callback(jpeg_event_t status); +static uint8_t *hal_mmap (uint32_t size, int *pmemFd); +static int hal_munmap (int pmem_fd, void *addr, size_t size); + +static uint8_t* hal_mmap(uint32_t size, int *pmemFd) +{ + void *ret; /* returned virtual address */ + int pmem_fd = open("/dev/pmem_adsp", O_RDWR); + + if (pmem_fd < 0) { + LOGE("hal_mmap: open /dev/pmem_adsp error %s!", + strerror(errno)); + return NULL; + } + + /* to make it page size aligned */ + // FIXME: use clp2() here + size = (size + 4095) & (~4095); + + LOGV("hal_mmap: pmem_fd %d size: %d", pmem_fd, size); + + ret = mmap(NULL, + size, + PROT_READ | PROT_WRITE, + MAP_SHARED, + pmem_fd, + 0); + + if (ret == MAP_FAILED) { + LOGE("hal_mmap: pmem mmap() error %s", strerror(errno)); + close(pmem_fd); + return NULL; + } + + *pmemFd = pmem_fd; + return (uint8_t *)ret; +} + +static int hal_munmap (int pmem_fd, void *addr, size_t size) +{ + int rc; + + // FIXME: use clp2()? + size = (size + 4095) & (~4095); + + LOGV("hal_munmap pmem_fd %d, size = %d, virt_addr = 0x%x", + pmem_fd, + size, (uint32_t)addr); + + rc = munmap(addr, size); + if (rc < 0) + LOGE("hal_munmap: munmap error %s", strerror(errno)); + + close(pmem_fd); + return rc; +} + +QualcommCameraHardware::QualcommCameraHardware() + : mParameters(), + mPreviewHeight(-1), + mPreviewWidth(-1), + mRawHeight(-1), + mRawWidth(-1), + mBrightness(0), + mZoomValuePrev(0), + mZoomValueCurr(0), + mZoomInitialised(false), + mCameraRunning(false), + mPreviewInitialized(false), + mFrameThreadRunning(false), + mReleasedRecordingFrame(false), + mShutterCallback(0), + mRawPictureCallback(0), + mJpegPictureCallback(0), + mPictureCallbackCookie(0), + mAutoFocusCallback(0), + mAutoFocusCallbackCookie(0), + mPreviewCallback(0), + mPreviewCallbackCookie(0), + mRecordingCallback(0), + mRecordingCallbackCookie(0), + mPreviewFrameSize(0), + mRawSize(0), + mCameraControlFd(-1), + mPmemThumbnailFd(-1), + mPmemSnapshotFd(-1), + mPreviewFrameOffset(0), + mThumbnailBuf(NULL), + mMainImageBuf(NULL), + mAutoFocusThreadRunning(false), + mAutoFocusFd(-1), + mInPreviewCallback(false) +{ + memset(&mZoom, 0, sizeof(mZoom)); + memset(&mFrameThread, 0, sizeof(mFrameThread)); + LOGV("constructor EX"); +} + +void QualcommCameraHardware::initDefaultParameters() +{ + CameraParameters p; + + LOGV("initDefaultParameters E"); + + preview_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING]; + p.setPreviewSize(ps->width, ps->height); + p.setPreviewFrameRate(15); + p.setPreviewFormat("yuv420sp"); // informative + p.setPictureFormat("jpeg"); // informative + + memset(&mDimension, 0, sizeof(mDimension)); + + mDimension.picture_width = DEFAULT_PICTURE_WIDTH; + mDimension.picture_height = DEFAULT_PICTURE_HEIGHT; + mDimension.display_width = ps->width; + mDimension.display_height = ps->height; + mDimension.ui_thumbnail_width = THUMBNAIL_WIDTH; + mDimension.ui_thumbnail_height = THUMBNAIL_HEIGHT; + + p.set("jpeg-thumbnail-width", THUMBNAIL_WIDTH_STR); // informative + p.set("jpeg-thumbnail-height", THUMBNAIL_HEIGHT_STR); // informative + //p.set("jpeg-thumbnail-quality", "90"); // FIXME: hook up through mm-camera + p.setPictureSize(mDimension.picture_width, mDimension.picture_height); + +#if 0 + p.set("gps-timestamp", "1199145600"); // Jan 1, 2008, 00:00:00 + p.set("gps-latitude", "37.736071"); // A little house in San Francisco + p.set("gps-longitude", "-122.441983"); + p.set("gps-altitude", "21"); // meters +#endif + + // This will happen only one in the lifetime of the mediaserver process. + // We do not free the _values arrays when we destroy the camera object. + INIT_VALUES_FOR(anti_banding); + INIT_VALUES_FOR(color_effects); + INIT_VALUES_FOR(whitebalance); + + p.set("anti-banding-values", anti_banding_values); + p.set("color-effects-values", color_effects_values); + p.set("whitebalance-values", whitebalance_values); + + // FIXME: we can specify these numeric ranges better + p.set("exposure-offset-values", "0,1,2,3,4,5,6,7,8,9,10"); + p.set("zoom-values", "0,1,2,3,4,5,6,7,8,9,10"); + + if (setParameters(p) != NO_ERROR) { + LOGE("Failed to set default parameters?!"); + } + + LOGV("initDefaultParameters X"); +} + +#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff) + +void QualcommCameraHardware::startCamera() +{ + LOGV("startCamera E"); +#if DLOPEN_LIBMMCAMERA + libmmcamera = ::dlopen("libqcamera.so", RTLD_NOW); + LOGV("loading libqcamera at %p", libmmcamera); + if (!libmmcamera) { + LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); + return; + } + + *(void **)&LINK_cam_frame = + ::dlsym(libmmcamera, "cam_frame"); + *(void **)&LINK_camframe_terminate = + ::dlsym(libmmcamera, "camframe_terminate"); + + *(void **)&LINK_jpeg_encoder_init = + ::dlsym(libmmcamera, "jpeg_encoder_init"); + + *(void **)&LINK_jpeg_encoder_encode = + ::dlsym(libmmcamera, "jpeg_encoder_encode"); + + *(void **)&LINK_jpeg_encoder_join = + ::dlsym(libmmcamera, "jpeg_encoder_join"); + + *(void **)&LINK_mmcamera_camframe_callback = + ::dlsym(libmmcamera, "mmcamera_camframe_callback"); + + *LINK_mmcamera_camframe_callback = receive_camframe_callback; + + *(void **)&LINK_mmcamera_jpegfragment_callback = + ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback"); + + *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback; + + *(void **)&LINK_mmcamera_jpeg_callback = + ::dlsym(libmmcamera, "mmcamera_jpeg_callback"); + + *LINK_mmcamera_jpeg_callback = receive_jpeg_callback; + + *(void**)&LINK_jpeg_encoder_setMainImageQuality = + ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality"); + + *(void **)&LINK_cam_conf = + ::dlsym(libmmcamera, "cam_conf"); +#else + mmcamera_camframe_callback = receive_camframe_callback; + mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback; + mmcamera_jpeg_callback = receive_jpeg_callback; +#endif // DLOPEN_LIBMMCAMERA + + /* The control thread is in libcamera itself. */ + mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR); + if (mCameraControlFd < 0) { + LOGE("startCamera X: %s open failed: %s!", + MSM_CAMERA_CONTROL, + strerror(errno)); + return; + } + + pthread_create(&mCamConfigThread, NULL, + LINK_cam_conf, NULL); + + LOGE("startCamera X"); +} + +status_t QualcommCameraHardware::dump(int fd, + const Vector& args) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + + // Dump internal primitives. + result.append("QualcommCameraHardware::dump"); + snprintf(buffer, 255, "preview width(%d) x height (%d)\n", + mPreviewWidth, mPreviewHeight); + result.append(buffer); + snprintf(buffer, 255, "raw width(%d) x height (%d)\n", + mRawWidth, mRawHeight); + result.append(buffer); + snprintf(buffer, 255, + "preview frame size(%d), raw size (%d), jpeg size (%d) " + "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize, + mJpegSize, mJpegMaxSize); + result.append(buffer); + write(fd, result.string(), result.size()); + + // Dump internal objects. + if (mPreviewHeap != 0) { + mPreviewHeap->dump(fd, args); + } + if (mRawHeap != 0) { + mRawHeap->dump(fd, args); + } + if (mJpegHeap != 0) { + mJpegHeap->dump(fd, args); + } + mParameters.dump(fd, args); + return NO_ERROR; +} + +bool QualcommCameraHardware::native_set_dimension(int camfd) +{ + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.type = CAMERA_SET_PARM_DIMENSION; + ctrlCmd.timeout_ms = 5000; + ctrlCmd.length = sizeof(cam_ctrl_dimension_t); + ctrlCmd.value = &mDimension; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_set_dimension: ioctl fd %d error %s", + camfd, + strerror(errno)); + return false; + } + + return ctrlCmd.status; +} + +bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) +{ + int rc; + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS; + ctrlCmd.length = sizeof(af_type); + ctrlCmd.value = &af_type; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) + LOGE("native_set_afmode: ioctl fd %d error %s\n", + camfd, + strerror(errno)); + + LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status); + return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE; +} + +bool native_cancel_afmode(int camfd, int af_fd) +{ + int rc; + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL; + ctrlCmd.length = 0; + ctrlCmd.resp_fd = af_fd; + + if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0) + LOGE("native_cancel_afmode: ioctl fd %d error %s\n", + camfd, + strerror(errno)); + return rc >= 0; +} + +void QualcommCameraHardware::reg_unreg_buf( + int camfd, + int width, + int height, + int pmempreviewfd, + uint8_t *prev_buf, + int pmem_type, + bool unregister, + bool active) +{ + uint32_t y_size; + struct msm_pmem_info_t pmemBuf; + uint32_t ioctl_cmd; + + if (prev_buf == NULL) + return; + + y_size = width * height; + + pmemBuf.type = pmem_type; + pmemBuf.fd = pmempreviewfd; + pmemBuf.vaddr = prev_buf; + pmemBuf.y_off = 0; + pmemBuf.cbcr_off = PAD_TO_WORD(y_size); + pmemBuf.active = active; + + ioctl_cmd = unregister ? + MSM_CAM_IOCTL_UNREGISTER_PMEM : + MSM_CAM_IOCTL_REGISTER_PMEM; + + LOGV("Entered reg_unreg_buf: camfd = %d, ioctl_cmd = %d, " + "pmemBuf.cbcr_off=%d, active=%d", + camfd, ioctl_cmd, pmemBuf.cbcr_off, active); + if (ioctl(camfd, ioctl_cmd, &pmemBuf) < 0) { + LOGE("reg_unreg_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s", + camfd, + strerror(errno)); + } +} + +bool QualcommCameraHardware::native_register_preview_bufs( + int camfd, + struct msm_frame_t *frame, + bool active) +{ + LOGV("mDimension.display_width = %d, display_height = %d", + mDimension.display_width, mDimension.display_height); + + reg_unreg_buf(camfd, + mDimension.display_width, + mDimension.display_height, + frame->fd, + (uint8_t *)frame->buffer, + MSM_PMEM_OUTPUT2, + false, + active); + + return true; +} + +bool QualcommCameraHardware::native_unregister_preview_bufs( + int camfd, + int pmempreviewfd, + uint8_t *prev_buf) +{ + reg_unreg_buf(camfd, + mDimension.display_width, + mDimension.display_height, + pmempreviewfd, + prev_buf, + MSM_PMEM_OUTPUT2, + true, + true); + return true; +} + +bool QualcommCameraHardware::native_start_preview(int camfd) +{ + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_START_PREVIEW; + ctrlCmd.length = 0; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s", + camfd, + strerror(errno)); + return false; + } + + return true; +} + +bool QualcommCameraHardware::native_register_snapshot_bufs( + int camfd, + int pmemthumbnailfd, + int pmemsnapshotfd, + uint8_t *thumbnail_buf, + uint8_t *main_img_buf) +{ + reg_unreg_buf(camfd, + mDimension.thumbnail_width, + mDimension.thumbnail_height, + pmemthumbnailfd, + thumbnail_buf, + MSM_PMEM_THUMBAIL, + false, + true); + + /* For original snapshot*/ + reg_unreg_buf(camfd, + mDimension.orig_picture_dx, + mDimension.orig_picture_dy, + pmemsnapshotfd, + main_img_buf, + MSM_PMEM_MAINIMG, + false, + true); + return true; +} + +bool QualcommCameraHardware::native_unregister_snapshot_bufs( + int camfd, + int thumb_fd, + int snap_fd, + uint8_t *thumbnail_buf, + uint8_t *main_img_buf) +{ + reg_unreg_buf(camfd, + mDimension.thumbnail_width, + mDimension.thumbnail_height, + thumb_fd, + thumbnail_buf, + MSM_PMEM_THUMBAIL, + true, + true); + + /* For original snapshot*/ + reg_unreg_buf(camfd, + mDimension.orig_picture_dx, + mDimension.orig_picture_dy, + snap_fd, + main_img_buf, + MSM_PMEM_MAINIMG, + true, + true); + + return true; +} + +bool QualcommCameraHardware::native_get_picture (int camfd) +{ + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.length = 0; + + if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) { + LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s", + camfd, + strerror(errno)); + return false; + } + + return true; +} + +bool QualcommCameraHardware::native_stop_preview(int camfd) +{ + struct msm_ctrl_cmd_t ctrlCmd; + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_STOP_PREVIEW; + ctrlCmd.length = 0; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_stop_preview: ioctl fd %d error %s", + camfd, + strerror(errno)); + return false; + } + + return true; +} + +bool QualcommCameraHardware::native_start_snapshot(int camfd) +{ + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_START_SNAPSHOT; + ctrlCmd.length = 0; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_start_snapshot: ioctl fd %d error %s", + camfd, + strerror(errno)); + return false; + } + + return true; +} + +bool QualcommCameraHardware::native_stop_snapshot (int camfd) +{ + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_STOP_SNAPSHOT; + ctrlCmd.length = 0; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_stop_snapshot: ioctl fd %d error %s", + camfd, + strerror(errno)); + return false; + } + + return true; +} + +bool QualcommCameraHardware::native_jpeg_encode ( + int thumb_fd, + int snap_fd, + uint8_t *thumbnail_buf, + uint8_t *main_img_buf) +{ + int jpeg_quality = mParameters.getInt("jpeg-quality"); + if (jpeg_quality >= 0) { + LOGV("native_jpeg_encode, current jpeg main img quality =%d", + jpeg_quality); + if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) { + LOGE("native_jpeg_encode set failed"); + return false; + } + } + + if (!LINK_jpeg_encoder_encode(&mDimension, + thumbnail_buf, thumb_fd, + main_img_buf, snap_fd)) { + LOGE("native_jpeg_encode: jpeg_encoder_encode failed."); + return false; + } + return true; +} + +void QualcommCameraHardware::runFrameThread(void *data) +{ + LOGV("runFrameThread E"); + + int cnt; + +#if DLOPEN_LIBMMCAMERA + // We need to maintain a reference to libqcamera.so for the duration of the + // frame thread, because we do not know when it will exit relative to the + // lifetime of this object. We do not want to dlclose() libqcamera while + // LINK_cam_frame is still running. + void *libhandle = ::dlopen("libqcamera.so", RTLD_NOW); + LOGV("loading libqcamera at %p", libhandle); + if (!libhandle) { + LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); + } + if (libhandle) +#endif + { + LINK_cam_frame(data); + } + + for (cnt = 0; cnt < kPreviewBufferCount; ++cnt) { + LOGV("unregisterPreviewBuf %d", cnt); + native_unregister_preview_bufs(mCameraControlFd, + frames[cnt].fd, + (uint8_t *)frames[cnt].buffer); + LOGV("do_munmap preview buffer %d, fd=%d, prev_buf=0x%lx, size=%d", + cnt, frames[cnt].fd, frames[cnt].buffer,frame_size); + int rc = hal_munmap(frames[cnt].fd, + (uint8_t *)frames[cnt].buffer,frame_size); + LOGV("do_munmap done with return value %d", rc); + } + LOGV("unregisterPreviewBuf %d", cnt); + mPreviewHeap.clear(); + +#if DLOPEN_LIBMMCAMERA + if (libhandle) { + ::dlclose(libhandle); + LOGV("FRAME: dlclose(libqcamera)"); + } +#endif + + mFrameThreadWaitLock.lock(); + mFrameThreadRunning = false; + mFrameThreadWait.signal(); + mFrameThreadWaitLock.unlock(); + + LOGV("runFrameThread X"); +} + +void *frame_thread(void *user) +{ + LOGV("frame_thread E"); + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->runFrameThread(user); + } + else LOGW("not starting frame thread: the object went away!"); + LOGV("frame_thread X"); + return NULL; +} + +bool QualcommCameraHardware::initPreview() +{ + // See comments in deinitPreview() for why we have to wait for the frame + // thread here, and why we can't use pthread_join(). + LOGI("initPreview E: preview size=%dx%d", mPreviewWidth, mPreviewHeight); + mFrameThreadWaitLock.lock(); + while (mFrameThreadRunning) { + LOGV("initPreview: waiting for old frame thread to complete."); + mFrameThreadWait.wait(mFrameThreadWaitLock); + LOGV("initPreview: old frame thread completed."); + } + mFrameThreadWaitLock.unlock(); + + int cnt = 0; + mPreviewFrameSize = mPreviewWidth * mPreviewHeight * 3/2; + mPreviewHeap = + new PreviewPmemPool(kRawFrameHeaderSize + + mPreviewWidth * mPreviewHeight * 3/2, + kPreviewBufferCount, + mPreviewFrameSize, + kRawFrameHeaderSize, + "preview"); + + if (!mPreviewHeap->initialized()) { + mPreviewHeap.clear(); + LOGE("initPreview X: could not initialize preview heap."); + return false; + } + + bool ret = true; + + mDimension.picture_width = DEFAULT_PICTURE_WIDTH; + mDimension.picture_height = DEFAULT_PICTURE_HEIGHT; + + ret = native_set_dimension(mCameraControlFd); + if(ret) { + frame_size = (clp2(mDimension.display_width * + mDimension.display_height * 3/2)); + for (cnt = 0; cnt < kPreviewBufferCount; cnt++) { + frames[cnt].fd = 0; + frames[cnt].buffer = + (unsigned long)hal_mmap(frame_size, &(frames[cnt].fd)); + frames[cnt].y_off = 0; + frames[cnt].cbcr_off = + mDimension.display_width * mDimension.display_height; + + if (frames[cnt].buffer == 0) { + LOGE("initPreview X: mmap failed!"); + return false; + } + + frames[cnt].path = MSM_FRAME_ENC; + + LOGV("do_mmap pbuf = 0x%lx, pmem_fd = %d", + frames[cnt].buffer, frames[cnt].fd); + native_register_preview_bufs(mCameraControlFd, + &frames[cnt], + cnt != kPreviewBufferCount - 1); + } + + + mFrameThreadWaitLock.lock(); + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + mFrameThreadRunning = !pthread_create(&mFrameThread, + &attr, + frame_thread, + &frames[kPreviewBufferCount-1]); + ret = mFrameThreadRunning; + mFrameThreadWaitLock.unlock(); + } + + LOGV("initPreview X: %d", ret); + return ret; +} + +void QualcommCameraHardware::deinitPreview(void) +{ + LOGI("deinitPreview E"); + + // When we call deinitPreview(), we signal to the frame thread that it + // needs to exit, but we DO NOT WAIT for it to complete here. The problem + // is that deinitPreview is sometimes called from the frame-thread's + // callback, when the refcount on the Camera client reaches zero. If we + // called pthread_join(), we would deadlock. So, we just call + // LINK_camframe_terminate() in deinitPreview(), which makes sure that + // after the preview callback returns, the camframe thread will exit. We + // could call pthread_join() in initPreview() to join the last frame + // thread. However, we would also have to call pthread_join() in release + // as well, shortly before we destoy the object; this would cause the same + // deadlock, since release(), like deinitPreview(), may also be called from + // the frame-thread's callback. This we have to make the frame thread + // detached, and use a separate mechanism to wait for it to complete. + + if (LINK_camframe_terminate() < 0) + LOGE("failed to stop the camframe thread: %s", + strerror(errno)); + LOGI("deinitPreview X"); +} + +bool QualcommCameraHardware::initRaw(bool initJpegHeap) +{ + LOGV("initRaw E: picture size=%dx%d", + mRawWidth, mRawHeight); + + mDimension.picture_width = mRawWidth; + mDimension.picture_height = mRawHeight; + + if(!native_set_dimension(mCameraControlFd)) { + LOGE("initRaw X: failed to set dimension"); + return false; + } + + mRawSize = mRawWidth * mRawHeight * 1.5; + + mJpegMaxSize = mRawWidth * mRawHeight * 1.5; + + LOGE("initRaw: clearing old mJpegHeap."); + mJpegHeap.clear(); + + // Snapshot + + LOGV("initRaw: initializing mRawHeap."); + mRawHeap = + new RawPmemPool("/dev/pmem_camera", + kRawFrameHeaderSize + mJpegMaxSize, + kRawBufferCount, + mRawSize, + kRawFrameHeaderSize, + "snapshot camera"); + + if (!mRawHeap->initialized()) { + LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp"); + mRawHeap = + new RawPmemPool("/dev/pmem_adsp", + kRawFrameHeaderSize + mJpegMaxSize, + kRawBufferCount, + mRawSize, + kRawFrameHeaderSize, + "snapshot camera"); + if (!mRawHeap->initialized()) { + LOGE("initRaw X: error initializing mRawHeap"); + mRawHeap.clear(); + return false; + } + } + + mMainImageBuf = (uint8_t *)mRawHeap->mHeap->base(); + mPmemSnapshotFd = mRawHeap->mHeap->getHeapID(); + + LOGV("do_mmap snapshot pbuf = 0x%p, pmem_fd = %d", + mMainImageBuf, mPmemSnapshotFd); + + // Thumbnails + + mThumbnailBuf = hal_mmap(THUMBNAIL_BUFFER_SIZE, &mPmemThumbnailFd); + LOGV("do_mmap thumbnail pbuf = 0x%p, pmem_fd = %d", + mThumbnailBuf, mPmemThumbnailFd); + if (mThumbnailBuf == NULL) { + mRawHeap.clear(); + LOGE("initRaw X: cannot allocate thumbnail memory"); + return false; + } + + native_register_snapshot_bufs(mCameraControlFd, + mPmemThumbnailFd, + mPmemSnapshotFd, + mThumbnailBuf, + mMainImageBuf); + + // Jpeg + + if (initJpegHeap) { + LOGV("initRaw: initializing mJpegHeap."); + mJpegHeap = + new AshmemPool(mJpegMaxSize, + kJpegBufferCount, + 0, // we do not know how big the picture wil be + 0, + "jpeg"); + if (!mJpegHeap->initialized()) { + LOGE("initRaw X failed: error initializing mJpegHeap."); + mJpegHeap.clear(); + mRawHeap.clear(); + return false; + } + } + + LOGV("initRaw X"); + return true; +} + +void QualcommCameraHardware::deinitRaw() +{ + LOGV("deinitRaw E"); + mJpegHeap.clear(); + mRawHeap.clear(); + + native_unregister_snapshot_bufs(mCameraControlFd, + mPmemThumbnailFd, mPmemSnapshotFd, + mThumbnailBuf, mMainImageBuf); + + if (mThumbnailBuf) { + hal_munmap(mPmemThumbnailFd, mThumbnailBuf, THUMBNAIL_BUFFER_SIZE); + mThumbnailBuf = NULL; + } + LOGV("deinitRaw X"); +} + +void QualcommCameraHardware::release() +{ + LOGV("release E"); + Mutex::Autolock l(&mLock); + + if (libmmcamera == NULL) { + LOGE("ERROR: multiple release!"); + return; + } + + int cnt, rc; + struct msm_ctrl_cmd_t ctrlCmd; + + if (mCameraRunning) { + cancelAutoFocus(); + if(mRecordingCallback != NULL) { + mRecordFrameLock.lock(); + mReleasedRecordingFrame = true; + mRecordWait.signal(); + mRecordFrameLock.unlock(); + } + stopPreviewInternal(); + } + + LINK_jpeg_encoder_join(); + deinitRaw(); + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.length = 0; + ctrlCmd.type = (uint16_t)CAMERA_EXIT; + ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel + if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) + LOGE("ioctl CAMERA_EXIT fd %d error %s", + mCameraControlFd, strerror(errno)); + rc = pthread_join(mCamConfigThread, NULL); + if (rc) + LOGE("config_thread exit failure: %s", strerror(errno)); + else + LOGV("pthread_join succeeded on config_thread"); + + close(mCameraControlFd); + mCameraControlFd = -1; + +#if DLOPEN_LIBMMCAMERA + if (libmmcamera) { + ::dlclose(libmmcamera); + LOGV("dlclose(libqcamera)"); + libmmcamera = NULL; + } +#endif + + LOGV("release X"); +} + +QualcommCameraHardware::~QualcommCameraHardware() +{ + LOGV("~QualcommCameraHardware E"); + singleton.clear(); + LOGV("~QualcommCameraHardware X"); +} + +sp QualcommCameraHardware::getRawHeap() const +{ + LOGV("getRawHeap"); + return mRawHeap != NULL ? mRawHeap->mHeap : NULL; +} + +sp QualcommCameraHardware::getPreviewHeap() const +{ + LOGV("getPreviewHeap"); + return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL; +} + +status_t QualcommCameraHardware::startPreviewInternal() +{ + if(mCameraRunning) { + LOGV("startPreview X: preview already running."); + return NO_ERROR; + } + + if (!mPreviewInitialized) { + mPreviewInitialized = initPreview(); + if (!mPreviewInitialized) { + LOGE("startPreview X initPreview failed. Not starting preview."); + return UNKNOWN_ERROR; + } + } + + mCameraRunning = native_start_preview(mCameraControlFd); + if(!mCameraRunning) { + deinitPreview(); + mPreviewInitialized = false; + LOGE("startPreview X: native_start_preview failed!"); + return UNKNOWN_ERROR; + } + + setSensorPreviewEffect(mCameraControlFd, mParameters.get("effect")); + setSensorWBLighting(mCameraControlFd, mParameters.get("whitebalance")); + setAntiBanding(mCameraControlFd, mParameters.get("antibanding")); + setBrightness(mParameters.getInt("exposure-offset")); + // FIXME: set nightshot, luma adaptatiom, zoom and check ranges + + LOGV("startPreview X"); + return NO_ERROR; +} + +status_t QualcommCameraHardware::startPreview(preview_callback cb, void *user) +{ + LOGV("startPreview E"); + Mutex::Autolock l(&mLock); + + { + Mutex::Autolock cbLock(&mCallbackLock); + mPreviewCallback = cb; + mPreviewCallbackCookie = user; + } + + return startPreviewInternal(); +} + +void QualcommCameraHardware::stopPreviewInternal() +{ + LOGV("stopPreviewInternal E: %d", mCameraRunning); + if (mCameraRunning) { + mCameraRunning = !native_stop_preview(mCameraControlFd); + if (!mCameraRunning && mPreviewInitialized) { + deinitPreview(); + mPreviewInitialized = false; + } + else LOGE("stopPreviewInternal: failed to stop preview"); + } + LOGV("stopPreviewInternal X: %d", mCameraRunning); +} + +void QualcommCameraHardware::stopPreview() +{ + LOGV("stopPreview: E"); + Mutex::Autolock l(&mLock); + + { + Mutex::Autolock cbLock(&mCallbackLock); + mAutoFocusCallback = NULL; + mPreviewCallback = NULL; + mPreviewCallbackCookie = NULL; + if(mRecordingCallback != NULL) + return; + } + + stopPreviewInternal(); + + LOGV("stopPreview: X"); +} + +void QualcommCameraHardware::runAutoFocus() +{ + mAutoFocusThreadLock.lock(); + mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR); + if (mAutoFocusFd < 0) { + LOGE("autofocus: cannot open %s: %s", + MSM_CAMERA_CONTROL, + strerror(errno)); + mAutoFocusThreadRunning = false; + mAutoFocusThreadLock.unlock(); + return; + } + + /* This will block until either AF completes or is cancelled. */ + LOGV("af start (fd %d)", mAutoFocusFd); + bool status = native_set_afmode(mAutoFocusFd, AF_MODE_AUTO); + LOGV("af done: %d", (int)status); + mAutoFocusThreadRunning = false; + close(mAutoFocusFd); + mAutoFocusFd = -1; + mAutoFocusThreadLock.unlock(); + + mCallbackLock.lock(); + autofocus_callback cb = mAutoFocusCallback; + void *data = mAutoFocusCallbackCookie; + mCallbackLock.unlock(); + if (cb != NULL) + cb(status, data); +} + +void QualcommCameraHardware::cancelAutoFocus() +{ + LOGV("cancelAutoFocus E"); + native_cancel_afmode(mCameraControlFd, mAutoFocusFd); + LOGV("cancelAutoFocus X"); +} + +void *auto_focus_thread(void *user) +{ + LOGV("auto_focus_thread E"); + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->runAutoFocus(); + } + else LOGW("not starting autofocus: the object went away!"); + LOGV("auto_focus_thread X"); + return NULL; +} + +status_t QualcommCameraHardware::autoFocus(autofocus_callback af_cb, + void *user) +{ + LOGV("autoFocus E"); + Mutex::Autolock l(&mLock); + + { + Mutex::Autolock cbl(&mCallbackLock); + mAutoFocusCallback = af_cb; + mAutoFocusCallbackCookie = user; + } + + if (mCameraControlFd < 0) { + LOGE("not starting autofocus: main control fd %d", mCameraControlFd); + return UNKNOWN_ERROR; + } + + { + mAutoFocusThreadLock.lock(); + if (!mAutoFocusThreadRunning) { + // Create a detatched thread here so that we don't have to wait + // for it when we cancel AF. + pthread_t thr; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + mAutoFocusThreadRunning = + !pthread_create(&thr, &attr, + auto_focus_thread, NULL); + if (!mAutoFocusThreadRunning) { + LOGE("failed to start autofocus thread"); + return UNKNOWN_ERROR; + } + } + mAutoFocusThreadLock.unlock(); + } + + LOGV("autoFocus X"); + return NO_ERROR; +} + +status_t QualcommCameraHardware::takePicture(shutter_callback shutter_cb, + raw_callback raw_cb, + jpeg_callback jpeg_cb, + void *user) +{ + LOGV("takePicture: E raw_cb = %p, jpeg_cb = %p", + raw_cb, jpeg_cb); + Mutex::Autolock l(&mLock); + + stopPreviewInternal(); + + if (!initRaw(jpeg_cb != NULL)) { + LOGE("initRaw failed. Not taking picture."); + return UNKNOWN_ERROR; + } + + { + Mutex::Autolock cbLock(&mCallbackLock); + mShutterCallback = shutter_cb; + mRawPictureCallback = raw_cb; + mJpegPictureCallback = jpeg_cb; + mPictureCallbackCookie = user; + } + + if (native_start_snapshot(mCameraControlFd) == false) { + LOGE("main: start_preview failed!"); + return UNKNOWN_ERROR; + } + receiveRawPicture(); + + LOGV("takePicture: X"); + return NO_ERROR; +} + +status_t QualcommCameraHardware::cancelPicture( + bool cancel_shutter, bool cancel_raw, bool cancel_jpeg) +{ + LOGV("cancelPicture: E cancel_shutter = %d, " + "cancel_raw = %d, cancel_jpeg = %d", + cancel_shutter, cancel_raw, cancel_jpeg); + Mutex::Autolock l(&mLock); + + { + Mutex::Autolock cbLock(&mCallbackLock); + if (cancel_shutter) mShutterCallback = NULL; + if (cancel_raw) mRawPictureCallback = NULL; + if (cancel_jpeg) mJpegPictureCallback = NULL; + } + + LOGV("cancelPicture: X"); + return NO_ERROR; +} + +status_t QualcommCameraHardware::setParameters( + const CameraParameters& params) +{ + LOGV("setParameters: E params = %p", ¶ms); + + Mutex::Autolock l(&mLock); + + mParameters = params; + + int width, height; + params.getPreviewSize(&width, &height); + LOGV("requested size %d x %d", width, height); + preview_size_type *ps = preview_sizes; + size_t i; + for (i = 0; i < PREVIEW_SIZE_COUNT; ++i, ++ps) { + if (width >= ps->width && height >= ps->height) + break; + } + if (i == PREVIEW_SIZE_COUNT) + ps--; + + LOGV("actual size %d x %d", ps->width, ps->height); + mParameters.setPreviewSize(ps->width, ps->height); + + mDimension.display_width = ps->width; + mDimension.display_height = ps->height; + + mParameters.getPreviewSize(&mPreviewWidth, &mPreviewHeight); + mParameters.getPictureSize(&mRawWidth, &mRawHeight); + + mPreviewWidth = (mPreviewWidth + 1) & ~1; + mPreviewHeight = (mPreviewHeight + 1) & ~1; + mRawHeight = (mRawHeight + 1) & ~1; + mRawWidth = (mRawWidth + 1) & ~1; + + if (mCameraRunning) + { + int val = mParameters.getInt("exposure-offset"); + if(val >= 0 && mBrightness != val) + { + if (val > BRIGHTNESS_MAX) + LOGE("invalid brightness value %d", val); + else { + LOGV("new brightness value %d", val); + mBrightness = val; + setBrightness(val); + } + } + + mZoomValueCurr = mParameters.getInt("zoom"); + if(mZoomValueCurr >= 0 && mZoomValueCurr <= ZOOM_MAX && + mZoomValuePrev != mZoomValueCurr) + { + bool ZoomDirectionIn = true; + if(mZoomValuePrev > mZoomValueCurr) + { + ZoomDirectionIn = false; + } + else + { + ZoomDirectionIn = true; + } + LOGV("new zoom value: %2.2f direction = %s", + mZoomValueCurr, (ZoomDirectionIn ? "in" : "out")); + mZoomValuePrev = mZoomValueCurr; + performZoom(ZoomDirectionIn); + } + + setSensorPreviewEffect(mCameraControlFd, mParameters.get("effect")); + setSensorWBLighting(mCameraControlFd, mParameters.get("whitebalance")); + setAntiBanding(mCameraControlFd, mParameters.get("antibanding")); + setBrightness(mParameters.getInt("exposure-offset")); + // FIXME: set nightshot, luma adaptatiom, zoom and check ranges + } + + LOGV("setParameters: X"); + return NO_ERROR ; +} + +CameraParameters QualcommCameraHardware::getParameters() const +{ + LOGV("getParameters: EX"); + return mParameters; +} + +extern "C" sp openCameraHardware() +{ + LOGV("openCameraHardware: call createInstance"); + return QualcommCameraHardware::createInstance(); +} + +wp QualcommCameraHardware::singleton; + +// If the hardware already exists, return a strong pointer to the current +// object. If not, create a new hardware object, put it in the singleton, +// and return it. +sp QualcommCameraHardware::createInstance() +{ + LOGV("createInstance: E"); + + Mutex::Autolock lock(&singleton_lock); + if (singleton != 0) { + sp hardware = singleton.promote(); + if (hardware != 0) { + LOGV("createInstance: X return existing hardware=%p", &(*hardware)); + return hardware; + } + } + + { + struct stat st; + int rc = stat("/dev/oncrpc", &st); + if (rc < 0) { + LOGV("createInstance: X failed to create hardware: %s", strerror(errno)); + return NULL; + } + } + + QualcommCameraHardware *cam = new QualcommCameraHardware(); + sp hardware(cam); + singleton = hardware; + + cam->startCamera(); + cam->initDefaultParameters(); + LOGV("createInstance: X created hardware=%p", &(*hardware)); + return hardware; +} + +// For internal use only, hence the strong pointer to the derived type. +sp QualcommCameraHardware::getInstance() +{ + sp hardware = singleton.promote(); + if (hardware != 0) { + // LOGV("getInstance: X old instance of hardware"); + return sp(static_cast(hardware.get())); + } else { + LOGV("getInstance: X new instance of hardware"); + return sp(); + } +} + +#if CAPTURE_RAW +static void dump_to_file(const char *fname, + uint8_t *buf, uint32_t size) +{ + int nw, cnt = 0; + uint32_t written = 0; + + LOGD("opening file [%s]", fname); + int fd = open(fname, O_RDWR | O_CREAT); + if (fd < 0) { + LOGE("failed to create file [%s]: %s", fname, strerror(errno)); + return; + } + + LOGD("writing %d uint8_ts to file [%s]", size, fname); + while (written < size) { + nw = ::write(fd, + buf + written, + size - written); + if (nw < 0) { + LOGE("failed to write to file [%s]: %s", + fname, strerror(errno)); + break; + } + written += nw; + cnt++; + } + LOGD("done writing %d uint8_ts to file [%s] in %d passes", + size, fname, cnt); + ::close(fd); +} +#endif // CAMERA_RAW + +void QualcommCameraHardware::receivePreviewFrame(struct msm_frame_t *frame) +{ +// LOGV("receivePreviewFrame E"); + + if (!mCameraRunning) { + LOGE("ignoring preview callback--camera has been stopped"); + return; + } + + mCallbackLock.lock(); + preview_callback pcb = mPreviewCallback; + void *pdata = mPreviewCallbackCookie; + recording_callback rcb = mRecordingCallback; + void *rdata = mRecordingCallbackCookie; + mCallbackLock.unlock(); + + // Find the offset within the heap of the current buffer. + ssize_t offset = + mPreviewWidth * mPreviewHeight * + mPreviewFrameOffset * 3 / 2; + + memcpy((uint8_t *)mPreviewHeap->mHeap->base() + offset, + (uint8_t *)frame->buffer, + mPreviewWidth * mPreviewHeight * 1.5); + + mInPreviewCallback = true; + if (pcb != NULL) + pcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], + pdata); + + mPreviewFrameOffset++; + mPreviewFrameOffset %= kPreviewBufferCount; + + if(rcb != NULL) { + Mutex::Autolock rLock(&mRecordFrameLock); + rcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], rdata); + while(mReleasedRecordingFrame != true) { + LOGV("block for release frame request/command"); + mRecordWait.wait(mRecordFrameLock); + } + mReleasedRecordingFrame = false; + } + mInPreviewCallback = false; + +// LOGV("receivePreviewFrame X"); +} + +status_t QualcommCameraHardware::startRecording( + recording_callback rcb, void *ruser) +{ + LOGV("startRecording E"); + Mutex::Autolock l(&mLock); + + { + Mutex::Autolock cbLock(&mCallbackLock); + mRecordingCallback = rcb; + mRecordingCallbackCookie = ruser; + } + + mReleasedRecordingFrame = false; + + return startPreviewInternal(); +} + +void QualcommCameraHardware::stopRecording() +{ + LOGV("stopRecording: E"); + Mutex::Autolock l(&mLock); + + { + Mutex::Autolock cbLock(&mCallbackLock); + mRecordingCallback = NULL; + mRecordingCallbackCookie = NULL; + + mRecordFrameLock.lock(); + mReleasedRecordingFrame = true; + mRecordWait.signal(); + mRecordFrameLock.unlock(); + + if(mPreviewCallback != NULL) { + LOGV("stopRecording: X, preview still in progress"); + return; + } + } + + stopPreviewInternal(); + LOGV("stopRecording: X"); +} + +void QualcommCameraHardware::releaseRecordingFrame( + const sp& mem __attribute__((unused))) +{ + LOGV("releaseRecordingFrame E"); + Mutex::Autolock l(&mLock); + Mutex::Autolock rLock(&mRecordFrameLock); + mReleasedRecordingFrame = true; + mRecordWait.signal(); + LOGV("releaseRecordingFrame X"); +} + +bool QualcommCameraHardware::recordingEnabled() +{ + Mutex::Autolock l(&mLock); + return mCameraRunning && mRecordingCallback != NULL; +} + +void +QualcommCameraHardware::notifyShutter() +{ + LOGV("notifyShutter: E"); + if (mShutterCallback) + mShutterCallback(mPictureCallbackCookie); + LOGV("notifyShutter: X"); +} + +static ssize_t snapshot_offset = 0; + +void +QualcommCameraHardware::receiveRawPicture() +{ + LOGV("receiveRawPicture: E"); + + int ret,rc,rete; +// Temporary fix for multiple snapshot issue on 8k: disabling shutter callback + Mutex::Autolock cbLock(&mCallbackLock); + notifyShutter(); + if (mRawPictureCallback != NULL) { + if(native_get_picture(mCameraControlFd)== false) { + LOGE("getPicture failed!"); + return; + } + ssize_t offset = (mRawWidth * mRawHeight * 1.5 * snapshot_offset); +#if CAPTURE_RAW + dump_to_file("/sdcard/photo.raw", + (uint8_t *)mMainImageBuf, mRawWidth * mRawHeight * 1.5 ); +#endif + mRawPictureCallback(mRawHeap->mBuffers[offset], + mPictureCallbackCookie); + } + else LOGV("Raw-picture callback was canceled--skipping."); + + if (mJpegPictureCallback != NULL) { + mJpegSize = 0; + if (LINK_jpeg_encoder_init()) { + if(native_jpeg_encode(mPmemThumbnailFd, + mPmemSnapshotFd, + mThumbnailBuf, + mMainImageBuf)) { + LOGV("receiveRawPicture: X (success)"); + return; + } + LOGE("jpeg encoding failed"); + } + else LOGE("receiveRawPicture X: jpeg_encoder_init failed."); + } + else LOGV("JPEG callback is NULL, not encoding image."); + deinitRaw(); + LOGV("receiveRawPicture: X"); +} + +void QualcommCameraHardware::receiveJpegPictureFragment( + uint8_t *buff_ptr, uint32_t buff_size) +{ + uint32_t remaining = mJpegHeap->mHeap->virtualSize(); + remaining -= mJpegSize; + uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base(); + + LOGV("receiveJpegPictureFragment size %d", buff_size); + if (buff_size > remaining) { + LOGE("receiveJpegPictureFragment: size %d exceeds what " + "remains in JPEG heap (%d), truncating", + buff_size, + remaining); + buff_size = remaining; + } + memcpy(base + mJpegSize, buff_ptr, buff_size); + mJpegSize += buff_size; +} + +void +QualcommCameraHardware::receiveJpegPicture(void) +{ + LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)", + mJpegSize, mJpegHeap->mBufferSize); + Mutex::Autolock cbLock(&mCallbackLock); + + int index = 0, rc; + + if (mJpegPictureCallback) { + // The reason we do not allocate into mJpegHeap->mBuffers[offset] is + // that the JPEG image's size will probably change from one snapshot + // to the next, so we cannot reuse the MemoryBase object. + sp buffer = new + MemoryBase(mJpegHeap->mHeap, + index * mJpegHeap->mBufferSize + + mJpegHeap->mFrameOffset, + mJpegSize); + + mJpegPictureCallback(buffer, mPictureCallbackCookie); + buffer = NULL; + } + else LOGV("JPEG callback was cancelled--not delivering image."); + + LINK_jpeg_encoder_join(); + deinitRaw(); + + LOGV("receiveJpegPicture: X callback done."); +} + +bool QualcommCameraHardware::previewEnabled() +{ +// Mutex::Autolock l(&mLock); + return mCameraRunning && mPreviewCallback != NULL; +} + +void QualcommCameraHardware::setSensorPreviewEffect(int camfd, const char *effect) +{ + LOGV("In setSensorPreviewEffect..."); + int effectsValue = 1; + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_SET_PARM_EFFECT; + ctrlCmd.length = sizeof(uint32_t); + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + effectsValue = attr_lookup(color_effects, effect, CAMERA_EFFECT_OFF); + ctrlCmd.value = (void *)&effectsValue; + LOGV("In setSensorPreviewEffect, color effect match %s %d", + effect, effectsValue); + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) + LOGE("setSensorPreviewEffect fd %d error %s", camfd, strerror(errno)); +} + +void QualcommCameraHardware::setSensorWBLighting(int camfd, const char *lighting) +{ + int lightingValue = 1; + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_SET_PARM_WB; + ctrlCmd.length = sizeof(uint32_t); + lightingValue = attr_lookup(whitebalance, lighting, CAMERA_WB_AUTO); + ctrlCmd.value = (void *)&lightingValue; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + LOGV("In setSensorWBLighting: match: %s: %d", + lighting, lightingValue); + if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) + LOGE("setSensorWBLighting: ioctl fd %d error %s", + camfd, strerror(errno)); +} + +void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) +{ + int antibandvalue = 0; + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_SET_PARM_ANTIBANDING; + ctrlCmd.length = sizeof(int32_t); + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + antibandvalue = attr_lookup(anti_banding, + antibanding, + CAMERA_ANTIBANDING_OFF); + ctrlCmd.value = (void *)&antibandvalue; + LOGV("In setAntiBanding: match: %s: %d", + antibanding, antibandvalue); + + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) + LOGE("setAntiBanding: ioctl %d error %s", + camfd, strerror(errno)); +} + +void QualcommCameraHardware::setBrightness(int brightness) +{ + struct msm_ctrl_cmd_t ctrlCmd; + LOGV("In setBrightness: %d", brightness); + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_SET_PARM_BRIGHTNESS; + ctrlCmd.length = sizeof(int); + ctrlCmd.value = (void *)&brightness; + ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel + + if(ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) + LOGE("setBrightness: ioctl fd %d error %s", + mCameraControlFd, strerror(errno)); +} + +bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) +{ + struct msm_ctrl_cmd_t ctrlCmd; + cam_parm_info_t *pZoom = (cam_parm_info_t *)pZm; + ctrlCmd.type = CAMERA_GET_PARM_ZOOM; + ctrlCmd.timeout_ms = 5000; + ctrlCmd.length = sizeof(cam_parm_info_t); + ctrlCmd.value = pZoom; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_get_zoom: ioctl fd %d error %s", + camfd, strerror(errno)); + return false; + } + + LOGV("native_get_zoom::current val=%d max=%d min=%d step val=%d", + pZoom->current_value, + pZoom->maximum_value, + pZoom->minimum_value, + pZoom->step_value); + + memcpy(pZoom, (cam_parm_info_t *)ctrlCmd.value, sizeof(cam_parm_info_t)); + + return ctrlCmd.status; +} + +bool QualcommCameraHardware::native_set_zoom(int camfd, void *pZm) +{ + struct msm_ctrl_cmd_t ctrlCmd; + + int32_t *pZoom = (int32_t *)pZm; + + ctrlCmd.type = CAMERA_SET_PARM_ZOOM; + ctrlCmd.timeout_ms = 5000; + ctrlCmd.length = sizeof(int32_t); + ctrlCmd.value = pZoom; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_set_zoom: ioctl fd %d error %s", + camfd, strerror(errno)); + return false; + } + + memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t)); + return ctrlCmd.status; +} + +void QualcommCameraHardware::performZoom(bool ZoomDir) +{ + if(mZoomInitialised == false) { + native_get_zoom(mCameraControlFd, (void *)&mZoom); + if(mZoom.maximum_value != 0) { + mZoomInitialised = true; + mZoom.step_value = (int) (mZoom.maximum_value/MAX_ZOOM_STEPS); + if( mZoom.step_value > 3 ) + mZoom.step_value = 3; + } + } + + if (ZoomDir) { + LOGV("performZoom::got zoom value of %d %d %d zoom in", + mZoom.current_value, + mZoom.step_value, + mZoom.maximum_value); + if((mZoom.current_value + mZoom.step_value) < mZoom.maximum_value) { + mZoom.current_value += mZoom.step_value; + LOGV("performZoom::Setting Zoom value of %d ",mZoom.current_value); + native_set_zoom(mCameraControlFd, (void *)&mZoom.current_value); + } + else { + LOGV("performZoom::not able to zoom in %d %d %d", + mZoom.current_value, + mZoom.step_value, + mZoom.maximum_value); + } + } + else + { + LOGV("performZoom::got zoom value of %d %d %d zoom out", + mZoom.current_value, + mZoom.step_value, + mZoom.minimum_value); + if((mZoom.current_value - mZoom.step_value) >= mZoom.minimum_value) + { + mZoom.current_value -= mZoom.step_value; + LOGV("performZoom::setting zoom value of %d ", + mZoom.current_value); + native_set_zoom(mCameraControlFd, (void *)&mZoom.current_value); + } + else + { + LOGV("performZoom::not able to zoom out %d %d %d", + mZoom.current_value, + mZoom.step_value, + mZoom.maximum_value); + } + } +} + +QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name) : + mBufferSize(buffer_size), + mNumBuffers(num_buffers), + mFrameSize(frame_size), + mFrameOffset(frame_offset), + mBuffers(NULL), mName(name) +{ + // empty +} + +void QualcommCameraHardware::MemPool::completeInitialization() +{ + // If we do not know how big the frame will be, we wait to allocate + // the buffers describing the individual frames until we do know their + // size. + + if (mFrameSize > 0) { + mBuffers = new sp[mNumBuffers]; + for (int i = 0; i < mNumBuffers; i++) { + mBuffers[i] = new + MemoryBase(mHeap, + i * mBufferSize + mFrameOffset, + mFrameSize); + } + } +} + +QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name) : + QualcommCameraHardware::MemPool(buffer_size, + num_buffers, + frame_size, + frame_offset, + name) +{ + LOGV("constructing MemPool %s backed by ashmem: " + "%d frames @ %d uint8_ts, offset %d, " + "buffer size %d", + mName, + num_buffers, frame_size, frame_offset, buffer_size); + + int page_mask = getpagesize() - 1; + int ashmem_size = buffer_size * num_buffers; + ashmem_size += page_mask; + ashmem_size &= ~page_mask; + + mHeap = new MemoryHeapBase(ashmem_size); + + completeInitialization(); +} + +QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool, + int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name) : + QualcommCameraHardware::MemPool(buffer_size, + num_buffers, + frame_size, + frame_offset, + name) +{ + LOGV("constructing MemPool %s backed by pmem pool %s: " + "%d frames @ %d bytes, offset %d, buffer size %d", + mName, + pmem_pool, num_buffers, frame_size, frame_offset, + buffer_size); + + // Make a new mmap'ed heap that can be shared across processes. + + mAlignedSize = clp2(buffer_size * num_buffers); + + sp masterHeap = + new MemoryHeapBase(pmem_pool, mAlignedSize, 0); + sp pmemHeap = new MemoryHeapPmem(masterHeap, 0); + if (pmemHeap->getHeapID() >= 0) { + pmemHeap->slap(); + masterHeap.clear(); + mHeap = pmemHeap; + pmemHeap.clear(); + + mFd = mHeap->getHeapID(); + if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) { + LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)", + pmem_pool, + ::strerror(errno), errno); + mHeap.clear(); + return; + } + + LOGE("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld", + pmem_pool, + mFd, + mSize.len); + + completeInitialization(); + } + else LOGE("pmem pool %s error: could not create master heap!", + pmem_pool); +} + +QualcommCameraHardware::PreviewPmemPool::PreviewPmemPool( + int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name) : + QualcommCameraHardware::PmemPool("/dev/pmem_adsp", + buffer_size, + num_buffers, + frame_size, + frame_offset, + name) +{ + LOGV("constructing PreviewPmemPool"); +} + +QualcommCameraHardware::PreviewPmemPool::~PreviewPmemPool() +{ + LOGV("destroying PreviewPmemPool"); + if(initialized()) { + void *base = mHeap->base(); + LOGV("destroying PreviewPmemPool"); + } +} + +QualcommCameraHardware::RawPmemPool::RawPmemPool( + const char *pmem_pool, + int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name) : + QualcommCameraHardware::PmemPool(pmem_pool, + buffer_size, + num_buffers, + frame_size, + frame_offset, + name) +{ + LOGV("constructing RawPmemPool"); +} + +QualcommCameraHardware::RawPmemPool::~RawPmemPool() +{ + LOGV("destroying RawPmemPool"); + if(initialized()) { + void *base = mHeap->base(); + LOGV("releasing RawPmemPool memory %p", + base); + } +} + +QualcommCameraHardware::MemPool::~MemPool() +{ + LOGV("destroying MemPool %s", mName); + if (mFrameSize > 0) + delete [] mBuffers; + mHeap.clear(); + LOGV("destroying MemPool %s completed", mName); +} + +status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector& args) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n"); + result.append(buffer); + if (mName) { + snprintf(buffer, 255, "mem pool name (%s)\n", mName); + result.append(buffer); + } + if (mHeap != 0) { + snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n", + mHeap->getBase(), mHeap->getSize(), + mHeap->getFlags(), mHeap->getDevice()); + result.append(buffer); + } + snprintf(buffer, 255, "buffer size (%d), number of buffers (%d)," + " frame size(%d), and frame offset(%d)\n", + mBufferSize, mNumBuffers, mFrameSize, mFrameOffset); + result.append(buffer); + write(fd, result.string(), result.size()); + return NO_ERROR; +} + +static void receive_camframe_callback(struct msm_frame_t *frame) +{ + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->receivePreviewFrame(frame); + } +} + +static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size) +{ + LOGV("receive_jpeg_fragment_callback E"); + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->receiveJpegPictureFragment(buff_ptr, buff_size); + } + LOGV("receive_jpeg_fragment_callback X"); +} + +static void receive_jpeg_callback(jpeg_event_t status) +{ + LOGV("receive_jpeg_callback E (completion status %d)", status); + if (status == JPEG_EVENT_DONE) { + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->receiveJpegPicture(); + } + } + LOGV("receive_jpeg_callback X"); +} + +}; // namespace android diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h new file mode 100755 index 0000000..eec6783 --- /dev/null +++ b/libcamera2/QualcommCameraHardware.h @@ -0,0 +1,286 @@ +/* +** Copyright 2008, Google Inc. +** +** 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. +*/ + +#ifndef ANDROID_HARDWARE_QUALCOMM_CAMERA_HARDWARE_H +#define ANDROID_HARDWARE_QUALCOMM_CAMERA_HARDWARE_H + +#include +#include +#include +#include + +extern "C" { +#include +#include +#include +} + +namespace android { + +class QualcommCameraHardware : public CameraHardwareInterface { +public: + + virtual sp getPreviewHeap() const; + virtual sp getRawHeap() const; + + virtual status_t dump(int fd, const Vector& args) const; + virtual status_t startPreview(preview_callback cb, void* user); + virtual void stopPreview(); + virtual status_t startRecording(recording_callback cb, void* user); + virtual void stopRecording(); + virtual bool recordingEnabled(); + virtual void releaseRecordingFrame(const sp& mem); + virtual status_t autoFocus(autofocus_callback, void *user); + virtual status_t takePicture(shutter_callback, + raw_callback, + jpeg_callback, + void* user); + virtual status_t cancelPicture(bool cancel_shutter, + bool cancel_raw, bool cancel_jpeg); + virtual status_t setParameters(const CameraParameters& params); + virtual CameraParameters getParameters() const; + + virtual void release(); + + static sp createInstance(); + static sp getInstance(); + + + + bool native_set_dimension (int camfd); + void reg_unreg_buf(int camfd, int width, int height, + int pmempreviewfd, uint8_t *prev_buf, + int pmem_type, + bool unregister, + bool active); + bool native_register_preview_bufs(int camfd, + struct msm_frame_t *frame,bool active); + bool native_unregister_preview_bufs(int camfd, int pmempreviewfd, + uint8_t *prev_buf); + + bool native_start_preview(int camfd); + bool native_stop_preview(int camfd); + + bool native_register_snapshot_bufs(int camfd, int pmemthumbnailfd, + int pmemsnapshotfd, + uint8_t *thumbnail_buf, + uint8_t *main_img_buf); + bool native_unregister_snapshot_bufs(int camfd, int pmemThumbnailfd, + int pmemSnapshotfd, + uint8_t *thumbnail_buf, + uint8_t *main_img_buf); + bool native_get_picture(int camfd); + bool native_start_snapshot(int camfd); + bool native_stop_snapshot(int camfd); + bool native_jpeg_encode (int pmemThumbnailfd, int pmemSnapshotfd, + uint8_t *thumbnail_buf, uint8_t *main_img_buf); + + bool native_set_zoom(int camfd, void *pZm); + bool native_get_zoom(int camfd, void *pZm); + + void receivePreviewFrame(struct msm_frame_t *frame); + void receiveJpegPicture(void); + void receiveJpegPictureFragment( + uint8_t * buff_ptr , uint32_t buff_size); + bool previewEnabled(); + + +private: + + QualcommCameraHardware(); + virtual ~QualcommCameraHardware(); + status_t startPreviewInternal(); + void stopPreviewInternal(); + friend void *auto_focus_thread(void *user); + void runAutoFocus(); + void cancelAutoFocus(); + + static wp singleton; + + /* These constants reflect the number of buffers that libmmcamera requires + for preview and raw, and need to be updated when libmmcamera + changes. + */ + static const int kPreviewBufferCount = 4; + static const int kRawBufferCount = 1; + static const int kJpegBufferCount = 1; + static const int kRawFrameHeaderSize = 0; + + //TODO: put the picture dimensions in the CameraParameters object; + CameraParameters mParameters; + int mPreviewHeight; + int mPreviewWidth; + int mRawHeight; + int mRawWidth; + unsigned int frame_size; + int mBrightness; + float mZoomValuePrev; + float mZoomValueCurr; + bool mZoomInitialised; + bool mCameraRunning; + bool mPreviewInitialized; + + // This class represents a heap which maintains several contiguous + // buffers. The heap may be backed by pmem (when pmem_pool contains + // the name of a /dev/pmem* file), or by ashmem (when pmem_pool == NULL). + + struct MemPool : public RefBase { + MemPool(int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name); + + virtual ~MemPool() = 0; + + void completeInitialization(); + bool initialized() const { + return mHeap != NULL && mHeap->base() != MAP_FAILED; + } + + virtual status_t dump(int fd, const Vector& args) const; + + int mBufferSize; + int mNumBuffers; + int mFrameSize; + int mFrameOffset; + sp mHeap; + sp *mBuffers; + + const char *mName; + }; + + struct AshmemPool : public MemPool { + AshmemPool(int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name); + }; + + struct PmemPool : public MemPool { + PmemPool(const char *pmem_pool, + int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name); + virtual ~PmemPool(){ } + int mFd; + uint32_t mAlignedSize; + struct pmem_region mSize; + }; + + struct PreviewPmemPool : public PmemPool { + virtual ~PreviewPmemPool(); + PreviewPmemPool(int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name); + }; + + struct RawPmemPool : public PmemPool { + virtual ~RawPmemPool(); + RawPmemPool(const char *pmem_pool, + int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name); + }; + + sp mPreviewHeap; + sp mRawHeap; + sp mJpegHeap; + + void startCamera(); + bool initPreview(); + void deinitPreview(); + bool initRaw(bool initJpegHeap); + void deinitRaw(); + + bool mFrameThreadRunning; + Mutex mFrameThreadWaitLock; + Condition mFrameThreadWait; + friend void *frame_thread(void *user); + void runFrameThread(void *data); + + void initDefaultParameters(); + + void setSensorPreviewEffect(int, const char*); + void setSensorWBLighting(int, const char*); + void setAntiBanding(int, const char*); + void setBrightness(int); + void performZoom(bool); + + Mutex mLock; + bool mReleasedRecordingFrame; + + void notifyShutter(); + + void receiveRawPicture(void); + + Mutex mCallbackLock; + Mutex mRecordLock; + Mutex mRecordFrameLock; + Condition mRecordWait; + Condition mStateWait; + + /* mJpegSize keeps track of the size of the accumulated JPEG. We clear it + when we are about to take a picture, so at any time it contains either + zero, or the size of the last JPEG picture taken. + */ + uint32_t mJpegSize; + + + shutter_callback mShutterCallback; + raw_callback mRawPictureCallback; + jpeg_callback mJpegPictureCallback; + void *mPictureCallbackCookie; + + autofocus_callback mAutoFocusCallback; + void *mAutoFocusCallbackCookie; + + preview_callback mPreviewCallback; + void *mPreviewCallbackCookie; + recording_callback mRecordingCallback; + void *mRecordingCallbackCookie; + unsigned int mPreviewFrameSize; + int mRawSize; + int mJpegMaxSize; + +#if DLOPEN_LIBMMCAMERA + void *libmmcamera; +#endif + + int mCameraControlFd; + cam_parm_info_t mZoom; + cam_ctrl_dimension_t mDimension; + int mPmemThumbnailFd; + int mPmemSnapshotFd; + ssize_t mPreviewFrameOffset; + uint8_t *mThumbnailBuf; + uint8_t *mMainImageBuf; + bool mAutoFocusThreadRunning; + Mutex mAutoFocusThreadLock; + int mAutoFocusFd; + + pthread_t mCamConfigThread; + pthread_t mFrameThread; + + struct msm_frame_t frames[kPreviewBufferCount]; + bool mInPreviewCallback; +}; + +}; // namespace android + +#endif From 0a1f5776735aaadc9d5a7923164b71749dded343 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Thu, 4 Jun 2009 13:36:10 -0700 Subject: [PATCH 03/29] Update reflects changes in type names in msm_camera.h. Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 44 +++++++++++++-------------- libcamera2/QualcommCameraHardware.h | 6 ++-- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 2209c8e..c11ea89 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -87,7 +87,7 @@ bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen, int (*LINK_camframe_terminate)(void); int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); // callbacks -void (**LINK_mmcamera_camframe_callback)(struct msm_frame_t *frame); +void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame); void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); @@ -99,7 +99,7 @@ void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); #define LINK_jpeg_encoder_encode jpeg_encoder_encode #define LINK_camframe_terminate camframe_terminate #define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality -extern void (*mmcamera_camframe_callback)(struct msm_frame_t *frame); +extern void (*mmcamera_camframe_callback)(struct msm_frame *frame); extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); extern void (*mmcamera_jpeg_callback)(jpeg_event_t status); @@ -215,7 +215,7 @@ namespace android { static Mutex singleton_lock; -static void receive_camframe_callback(struct msm_frame_t *frame); +static void receive_camframe_callback(struct msm_frame *frame); static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size); static void receive_jpeg_callback(jpeg_event_t status); static uint8_t *hal_mmap (uint32_t size, int *pmemFd); @@ -475,7 +475,7 @@ status_t QualcommCameraHardware::dump(int fd, bool QualcommCameraHardware::native_set_dimension(int camfd) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.type = CAMERA_SET_PARM_DIMENSION; ctrlCmd.timeout_ms = 5000; @@ -496,7 +496,7 @@ bool QualcommCameraHardware::native_set_dimension(int camfd) bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) { int rc; - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS; @@ -516,7 +516,7 @@ bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) bool native_cancel_afmode(int camfd, int af_fd) { int rc; - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL; @@ -541,7 +541,7 @@ void QualcommCameraHardware::reg_unreg_buf( bool active) { uint32_t y_size; - struct msm_pmem_info_t pmemBuf; + struct msm_pmem_info pmemBuf; uint32_t ioctl_cmd; if (prev_buf == NULL) @@ -572,7 +572,7 @@ void QualcommCameraHardware::reg_unreg_buf( bool QualcommCameraHardware::native_register_preview_bufs( int camfd, - struct msm_frame_t *frame, + struct msm_frame *frame, bool active) { LOGV("mDimension.display_width = %d, display_height = %d", @@ -608,7 +608,7 @@ bool QualcommCameraHardware::native_unregister_preview_bufs( bool QualcommCameraHardware::native_start_preview(int camfd) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_START_PREVIEW; @@ -684,7 +684,7 @@ bool QualcommCameraHardware::native_unregister_snapshot_bufs( bool QualcommCameraHardware::native_get_picture (int camfd) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.length = 0; @@ -701,7 +701,7 @@ bool QualcommCameraHardware::native_get_picture (int camfd) bool QualcommCameraHardware::native_stop_preview(int camfd) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_STOP_PREVIEW; ctrlCmd.length = 0; @@ -719,7 +719,7 @@ bool QualcommCameraHardware::native_stop_preview(int camfd) bool QualcommCameraHardware::native_start_snapshot(int camfd) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_START_SNAPSHOT; @@ -738,7 +738,7 @@ bool QualcommCameraHardware::native_start_snapshot(int camfd) bool QualcommCameraHardware::native_stop_snapshot (int camfd) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_STOP_SNAPSHOT; @@ -1064,7 +1064,7 @@ void QualcommCameraHardware::release() } int cnt, rc; - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; if (mCameraRunning) { cancelAutoFocus(); @@ -1523,7 +1523,7 @@ static void dump_to_file(const char *fname, } #endif // CAMERA_RAW -void QualcommCameraHardware::receivePreviewFrame(struct msm_frame_t *frame) +void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) { // LOGV("receivePreviewFrame E"); @@ -1742,7 +1742,7 @@ void QualcommCameraHardware::setSensorPreviewEffect(int camfd, const char *effe { LOGV("In setSensorPreviewEffect..."); int effectsValue = 1; - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_SET_PARM_EFFECT; @@ -1760,7 +1760,7 @@ void QualcommCameraHardware::setSensorPreviewEffect(int camfd, const char *effe void QualcommCameraHardware::setSensorWBLighting(int camfd, const char *lighting) { int lightingValue = 1; - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_SET_PARM_WB; @@ -1778,7 +1778,7 @@ void QualcommCameraHardware::setSensorWBLighting(int camfd, const char *lighting void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) { int antibandvalue = 0; - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_SET_PARM_ANTIBANDING; @@ -1799,7 +1799,7 @@ void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) void QualcommCameraHardware::setBrightness(int brightness) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; LOGV("In setBrightness: %d", brightness); ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_SET_PARM_BRIGHTNESS; @@ -1814,7 +1814,7 @@ void QualcommCameraHardware::setBrightness(int brightness) bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; cam_parm_info_t *pZoom = (cam_parm_info_t *)pZm; ctrlCmd.type = CAMERA_GET_PARM_ZOOM; ctrlCmd.timeout_ms = 5000; @@ -1841,7 +1841,7 @@ bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) bool QualcommCameraHardware::native_set_zoom(int camfd, void *pZm) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; int32_t *pZoom = (int32_t *)pZm; @@ -2103,7 +2103,7 @@ status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector& a return NO_ERROR; } -static void receive_camframe_callback(struct msm_frame_t *frame) +static void receive_camframe_callback(struct msm_frame *frame) { sp obj = QualcommCameraHardware::getInstance(); if (obj != 0) { diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index eec6783..06c38a2 100755 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -67,7 +67,7 @@ public: bool unregister, bool active); bool native_register_preview_bufs(int camfd, - struct msm_frame_t *frame,bool active); + struct msm_frame *frame,bool active); bool native_unregister_preview_bufs(int camfd, int pmempreviewfd, uint8_t *prev_buf); @@ -91,7 +91,7 @@ public: bool native_set_zoom(int camfd, void *pZm); bool native_get_zoom(int camfd, void *pZm); - void receivePreviewFrame(struct msm_frame_t *frame); + void receivePreviewFrame(struct msm_frame *frame); void receiveJpegPicture(void); void receiveJpegPictureFragment( uint8_t * buff_ptr , uint32_t buff_size); @@ -277,7 +277,7 @@ private: pthread_t mCamConfigThread; pthread_t mFrameThread; - struct msm_frame_t frames[kPreviewBufferCount]; + struct msm_frame frames[kPreviewBufferCount]; bool mInPreviewCallback; }; From 88dbb2fc3f84ad560c68345aa7e9b8df5f680bda Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Tue, 26 May 2009 18:22:13 -0700 Subject: [PATCH 04/29] disable libcamera and enable libcamera2 Signed-off-by: Iliyan Malchev --- libcamera2/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk index dab1c17..0a60554 100755 --- a/libcamera2/Android.mk +++ b/libcamera2/Android.mk @@ -1,4 +1,4 @@ -BUILD_LIBCAMERA:= +BUILD_LIBCAMERA:=true ifeq ($(BUILD_LIBCAMERA),true) # When zero we link against libmmcamera; when 1, we dlopen libmmcamera. From 366cd7e1e3a4f10c190f7afe5bcb45e9cb949893 Mon Sep 17 00:00:00 2001 From: James Dong Date: Fri, 5 Jun 2009 17:59:32 -0700 Subject: [PATCH 05/29] Restore the support for SQVGA (bug 1901755) --- libcamera2/QualcommCameraHardware.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index c11ea89..2987ee1 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -118,6 +118,7 @@ static preview_size_type preview_sizes[] = { { 480, 320 }, // HVGA { 352, 288 }, // CIF { 320, 240 }, // QVGA + { 240, 160 }, // SQVGA { 176, 144 }, // QCIF }; From 59b25b06c88aeab1e13e8ca68a24c3906822116c Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Wed, 10 Jun 2009 15:32:57 -0700 Subject: [PATCH 06/29] libcamera2: update the frame offset after we call the recording callback Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 2987ee1..c5231ca 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1554,9 +1554,6 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) pcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], pdata); - mPreviewFrameOffset++; - mPreviewFrameOffset %= kPreviewBufferCount; - if(rcb != NULL) { Mutex::Autolock rLock(&mRecordFrameLock); rcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], rdata); @@ -1568,6 +1565,9 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) } mInPreviewCallback = false; + mPreviewFrameOffset++; + mPreviewFrameOffset %= kPreviewBufferCount; + // LOGV("receivePreviewFrame X"); } From f5e21dce16dd8611b6c0adc577ec44155b0eb164 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Wed, 10 Jun 2009 16:46:51 -0700 Subject: [PATCH 07/29] remove floats from libcamera2 Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 12 ++++++------ libcamera2/QualcommCameraHardware.h | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index c5231ca..708a62d 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -958,9 +958,9 @@ bool QualcommCameraHardware::initRaw(bool initJpegHeap) return false; } - mRawSize = mRawWidth * mRawHeight * 1.5; + mRawSize = mRawWidth * mRawHeight * 3 / 2; - mJpegMaxSize = mRawWidth * mRawHeight * 1.5; + mJpegMaxSize = mRawWidth * mRawHeight * 3 / 2; LOGE("initRaw: clearing old mJpegHeap."); mJpegHeap.clear(); @@ -1412,7 +1412,7 @@ status_t QualcommCameraHardware::setParameters( { ZoomDirectionIn = true; } - LOGV("new zoom value: %2.2f direction = %s", + LOGV("new zoom value: %d direction = %s", mZoomValueCurr, (ZoomDirectionIn ? "in" : "out")); mZoomValuePrev = mZoomValueCurr; performZoom(ZoomDirectionIn); @@ -1547,7 +1547,7 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) memcpy((uint8_t *)mPreviewHeap->mHeap->base() + offset, (uint8_t *)frame->buffer, - mPreviewWidth * mPreviewHeight * 1.5); + mPreviewWidth * mPreviewHeight * 3 / 2); mInPreviewCallback = true; if (pcb != NULL) @@ -1655,10 +1655,10 @@ QualcommCameraHardware::receiveRawPicture() LOGE("getPicture failed!"); return; } - ssize_t offset = (mRawWidth * mRawHeight * 1.5 * snapshot_offset); + ssize_t offset = (mRawWidth * mRawHeight * snapshot_offset * 3 / 2); #if CAPTURE_RAW dump_to_file("/sdcard/photo.raw", - (uint8_t *)mMainImageBuf, mRawWidth * mRawHeight * 1.5 ); + (uint8_t *)mMainImageBuf, mRawWidth * mRawHeight * 3 / 2); #endif mRawPictureCallback(mRawHeap->mBuffers[offset], mPictureCallbackCookie); diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index 06c38a2..b5707b6 100755 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -125,12 +125,12 @@ private: int mPreviewWidth; int mRawHeight; int mRawWidth; - unsigned int frame_size; - int mBrightness; - float mZoomValuePrev; - float mZoomValueCurr; - bool mZoomInitialised; - bool mCameraRunning; + unsigned int frame_size; + int mBrightness; + int mZoomValuePrev; + int mZoomValueCurr; + bool mZoomInitialised; + bool mCameraRunning; bool mPreviewInitialized; // This class represents a heap which maintains several contiguous From ed604c67eedbb7e8ab02df143cf2ef26bfe023f6 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Wed, 10 Jun 2009 14:48:33 -0700 Subject: [PATCH 08/29] libcamera: default brightness to 5 when not specified by camera Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 53 ++++++++++++++------------- libcamera2/QualcommCameraHardware.h | 2 +- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 708a62d..80a8696 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -72,6 +72,7 @@ extern "C" { #define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(preview_size_type)) #define BRIGHTNESS_MAX 10 // FIXME: this should correlate with brightness-values +#define BRIGHTNESS_DEF 5 // FIXME: this should correlate with brightness-values #define ZOOM_MAX 10 // FIXME: this should correlate with zoom-values #if DLOPEN_LIBMMCAMERA @@ -281,7 +282,7 @@ QualcommCameraHardware::QualcommCameraHardware() mPreviewWidth(-1), mRawHeight(-1), mRawWidth(-1), - mBrightness(0), + mBrightness(BRIGHTNESS_DEF), mZoomValuePrev(0), mZoomValueCurr(0), mZoomInitialised(false), @@ -1153,7 +1154,7 @@ status_t QualcommCameraHardware::startPreviewInternal() setSensorPreviewEffect(mCameraControlFd, mParameters.get("effect")); setSensorWBLighting(mCameraControlFd, mParameters.get("whitebalance")); setAntiBanding(mCameraControlFd, mParameters.get("antibanding")); - setBrightness(mParameters.getInt("exposure-offset")); + setBrightness(); // FIXME: set nightshot, luma adaptatiom, zoom and check ranges LOGV("startPreview X"); @@ -1387,17 +1388,7 @@ status_t QualcommCameraHardware::setParameters( if (mCameraRunning) { - int val = mParameters.getInt("exposure-offset"); - if(val >= 0 && mBrightness != val) - { - if (val > BRIGHTNESS_MAX) - LOGE("invalid brightness value %d", val); - else { - LOGV("new brightness value %d", val); - mBrightness = val; - setBrightness(val); - } - } + setBrightness(); mZoomValueCurr = mParameters.getInt("zoom"); if(mZoomValueCurr >= 0 && mZoomValueCurr <= ZOOM_MAX && @@ -1421,7 +1412,6 @@ status_t QualcommCameraHardware::setParameters( setSensorPreviewEffect(mCameraControlFd, mParameters.get("effect")); setSensorWBLighting(mCameraControlFd, mParameters.get("whitebalance")); setAntiBanding(mCameraControlFd, mParameters.get("antibanding")); - setBrightness(mParameters.getInt("exposure-offset")); // FIXME: set nightshot, luma adaptatiom, zoom and check ranges } @@ -1798,19 +1788,32 @@ void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) camfd, strerror(errno)); } -void QualcommCameraHardware::setBrightness(int brightness) +void QualcommCameraHardware::setBrightness() { - struct msm_ctrl_cmd ctrlCmd; - LOGV("In setBrightness: %d", brightness); - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_SET_PARM_BRIGHTNESS; - ctrlCmd.length = sizeof(int); - ctrlCmd.value = (void *)&brightness; - ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel + int val = mParameters.getInt("exposure-offset"); + if (val < 0) + val = BRIGHTNESS_DEF; + else if (val > BRIGHTNESS_MAX) + val = BRIGHTNESS_MAX; - if(ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) - LOGE("setBrightness: ioctl fd %d error %s", - mCameraControlFd, strerror(errno)); + if (mBrightness != val) { + LOGV("new brightness value %d", val); + mBrightness = val; + + struct msm_ctrl_cmd ctrlCmd; + LOGV("In setBrightness: %d", val); + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_SET_PARM_BRIGHTNESS; + ctrlCmd.length = sizeof(int); + ctrlCmd.value = (void *)&val; + // FIXME: this will be put in by the kernel + ctrlCmd.resp_fd = mCameraControlFd; + + if(ioctl(mCameraControlFd, + MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) + LOGE("setBrightness: ioctl fd %d error %s", + mCameraControlFd, strerror(errno)); + } } bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index b5707b6..02fa598 100755 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -219,7 +219,7 @@ private: void setSensorPreviewEffect(int, const char*); void setSensorWBLighting(int, const char*); void setAntiBanding(int, const char*); - void setBrightness(int); + void setBrightness(void); void performZoom(bool); Mutex mLock; From 32b7f2804eb66a6677826833057ca93bef78b870 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Wed, 10 Jun 2009 14:49:11 -0700 Subject: [PATCH 09/29] libcamera: avoid a race condition on starting and stopping a recording precondition: preview is running -- call startRecording() -- a preview frame arrives, causing the record callback to be called, and then blocks on mRecordWait.wait() -- call stopRecording(), which sets mReleasedRecordingFrame and signals mRecordWait; -- call startRecording(), which clears mReleasedRecordingFrame; -- receivePreviewFrame() wakes up, checks mReleasedRecordingFrame, and blocks again on mRecordWait.wait(), without having notified the client. Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 80a8696..718f6bf 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1547,7 +1547,7 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) if(rcb != NULL) { Mutex::Autolock rLock(&mRecordFrameLock); rcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], rdata); - while(mReleasedRecordingFrame != true) { + if (mReleasedRecordingFrame != true) { LOGV("block for release frame request/command"); mRecordWait.wait(mRecordFrameLock); } From c11ce4c954ddb62f738b868737d01cc9d3b06e8e Mon Sep 17 00:00:00 2001 From: James Dong Date: Wed, 10 Jun 2009 19:59:25 -0700 Subject: [PATCH 10/29] Fix deadlock in camera hal when auto focus failed --- libcamera2/QualcommCameraHardware.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 718f6bf..8952470 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1288,6 +1288,7 @@ status_t QualcommCameraHardware::autoFocus(autofocus_callback af_cb, auto_focus_thread, NULL); if (!mAutoFocusThreadRunning) { LOGE("failed to start autofocus thread"); + mAutoFocusThreadLock.unlock(); return UNKNOWN_ERROR; } } From 2e8a9ddd4ceb49aa66abc0a62882ff641ae37f28 Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Wed, 10 Jun 2009 14:27:39 +0800 Subject: [PATCH 11/29] Cancel autofocus in stopPreview. --- libcamera2/QualcommCameraHardware.cpp | 32 +++++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) mode change 100755 => 100644 libcamera2/QualcommCameraHardware.cpp diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp old mode 100755 new mode 100644 index 8952470..449a610 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1069,7 +1069,6 @@ void QualcommCameraHardware::release() struct msm_ctrl_cmd ctrlCmd; if (mCameraRunning) { - cancelAutoFocus(); if(mRecordingCallback != NULL) { mRecordFrameLock.lock(); mReleasedRecordingFrame = true; @@ -1179,6 +1178,16 @@ void QualcommCameraHardware::stopPreviewInternal() { LOGV("stopPreviewInternal E: %d", mCameraRunning); if (mCameraRunning) { + // Cancel auto focus. + if (mAutoFocusCallback) { + { + Mutex::Autolock cbLock(&mCallbackLock); + mAutoFocusCallback = NULL; + mAutoFocusCallbackCookie = NULL; + } + cancelAutoFocus(); + } + mCameraRunning = !native_stop_preview(mCameraControlFd); if (!mCameraRunning && mPreviewInitialized) { deinitPreview(); @@ -1196,7 +1205,6 @@ void QualcommCameraHardware::stopPreview() { Mutex::Autolock cbLock(&mCallbackLock); - mAutoFocusCallback = NULL; mPreviewCallback = NULL; mPreviewCallbackCookie = NULL; if(mRecordingCallback != NULL) @@ -1236,6 +1244,11 @@ void QualcommCameraHardware::runAutoFocus() mCallbackLock.unlock(); if (cb != NULL) cb(status, data); + + mCallbackLock.lock(); + mAutoFocusCallback = NULL; + mAutoFocusCallbackCookie = NULL; + mCallbackLock.unlock(); } void QualcommCameraHardware::cancelAutoFocus() @@ -1263,17 +1276,22 @@ status_t QualcommCameraHardware::autoFocus(autofocus_callback af_cb, LOGV("autoFocus E"); Mutex::Autolock l(&mLock); + if (mCameraControlFd < 0) { + LOGE("not starting autofocus: main control fd %d", mCameraControlFd); + return UNKNOWN_ERROR; + } + + if (mAutoFocusCallback != NULL) { + LOGW("Auto focus is already in progress"); + return mAutoFocusCallback == af_cb ? NO_ERROR : INVALID_OPERATION; + } + { Mutex::Autolock cbl(&mCallbackLock); mAutoFocusCallback = af_cb; mAutoFocusCallbackCookie = user; } - if (mCameraControlFd < 0) { - LOGE("not starting autofocus: main control fd %d", mCameraControlFd); - return UNKNOWN_ERROR; - } - { mAutoFocusThreadLock.lock(); if (!mAutoFocusThreadRunning) { From 93cde78899419a32da75d01e3de1ddc785b470ee Mon Sep 17 00:00:00 2001 From: Chih-Chung Chang Date: Mon, 15 Jun 2009 14:20:59 +0800 Subject: [PATCH 12/29] Accept parameter "jpeg-thumbnail-quality" to specify thumbnail quality. --- libcamera2/Android.mk | 0 libcamera2/QualcommCameraHardware.cpp | 17 ++++++++++++++++- libcamera2/QualcommCameraHardware.h | 0 3 files changed, 16 insertions(+), 1 deletion(-) mode change 100755 => 100644 libcamera2/Android.mk mode change 100755 => 100644 libcamera2/QualcommCameraHardware.h diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk old mode 100755 new mode 100644 diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 449a610..886982c 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -87,6 +87,7 @@ bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen, const uint8_t *snapshotbuf, int snapshotfd); int (*LINK_camframe_terminate)(void); int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); +int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality); // callbacks void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame); void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, @@ -100,6 +101,7 @@ void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); #define LINK_jpeg_encoder_encode jpeg_encoder_encode #define LINK_camframe_terminate camframe_terminate #define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality +#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality extern void (*mmcamera_camframe_callback)(struct msm_frame *frame); extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); @@ -340,7 +342,7 @@ void QualcommCameraHardware::initDefaultParameters() p.set("jpeg-thumbnail-width", THUMBNAIL_WIDTH_STR); // informative p.set("jpeg-thumbnail-height", THUMBNAIL_HEIGHT_STR); // informative - //p.set("jpeg-thumbnail-quality", "90"); // FIXME: hook up through mm-camera + p.set("jpeg-thumbnail-quality", "90"); p.setPictureSize(mDimension.picture_width, mDimension.picture_height); #if 0 @@ -416,6 +418,9 @@ void QualcommCameraHardware::startCamera() *(void**)&LINK_jpeg_encoder_setMainImageQuality = ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality"); + *(void**)&LINK_jpeg_encoder_setThumbnailQuality = + ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality"); + *(void **)&LINK_cam_conf = ::dlsym(libmmcamera, "cam_conf"); #else @@ -773,6 +778,16 @@ bool QualcommCameraHardware::native_jpeg_encode ( } } + int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality"); + if (thumbnail_quality >= 0) { + LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d", + thumbnail_quality); + if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) { + LOGE("native_jpeg_encode set failed"); + return false; + } + } + if (!LINK_jpeg_encoder_encode(&mDimension, thumbnail_buf, thumb_fd, main_img_buf, snap_fd)) { diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h old mode 100755 new mode 100644 From 4f48dacadaf5cc7fe8fd3c891b147708e005d196 Mon Sep 17 00:00:00 2001 From: Chih-Chung Chang Date: Mon, 15 Jun 2009 17:00:23 +0800 Subject: [PATCH 13/29] Add set rotation function. --- libcamera2/QualcommCameraHardware.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 886982c..646f849 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -88,6 +88,7 @@ bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen, int (*LINK_camframe_terminate)(void); int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality); +int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation); // callbacks void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame); void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, @@ -102,6 +103,7 @@ void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); #define LINK_camframe_terminate camframe_terminate #define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality #define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality +#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation extern void (*mmcamera_camframe_callback)(struct msm_frame *frame); extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); @@ -421,6 +423,9 @@ void QualcommCameraHardware::startCamera() *(void**)&LINK_jpeg_encoder_setThumbnailQuality = ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality"); + *(void**)&LINK_jpeg_encoder_setRotation = + ::dlsym(libmmcamera, "jpeg_encoder_setRotation"); + *(void **)&LINK_cam_conf = ::dlsym(libmmcamera, "cam_conf"); #else @@ -773,7 +778,7 @@ bool QualcommCameraHardware::native_jpeg_encode ( LOGV("native_jpeg_encode, current jpeg main img quality =%d", jpeg_quality); if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) { - LOGE("native_jpeg_encode set failed"); + LOGE("native_jpeg_encode set jpeg-quality failed"); return false; } } @@ -783,7 +788,16 @@ bool QualcommCameraHardware::native_jpeg_encode ( LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d", thumbnail_quality); if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) { - LOGE("native_jpeg_encode set failed"); + LOGE("native_jpeg_encode set thumbnail-quality failed"); + return false; + } + } + + int rotation = mParameters.getInt("rotation"); + if (rotation >= 0) { + LOGV("native_jpeg_encode, rotation = %d", rotation); + if(!LINK_jpeg_encoder_setRotation(rotation)) { + LOGE("native_jpeg_encode set rotation failed"); return false; } } From 9e7909b4391d3661a28411ae7783f8050a81efcf Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Mon, 15 Jun 2009 15:22:17 -0700 Subject: [PATCH 14/29] libcamera2: update to match new libqcamera.so Signed-off-by: Iliyan Malchev --- libcamera2/Android.mk | 2 +- libcamera2/QualcommCameraHardware.cpp | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk index 0a60554..26eb4a5 100644 --- a/libcamera2/Android.mk +++ b/libcamera2/Android.mk @@ -23,7 +23,7 @@ LOCAL_C_INCLUDES+= \ LOCAL_SHARED_LIBRARIES:= libutils libui liblog ifneq ($(DLOPEN_LIBMMCAMERA),1) -LOCAL_SHARED_LIBRARIES+= libmmcamera +LOCAL_SHARED_LIBRARIES+= libqcamera else LOCAL_SHARED_LIBRARIES+= libdl endif diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 646f849..ee0ac66 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -84,7 +84,8 @@ bool (*LINK_jpeg_encoder_init)(); void (*LINK_jpeg_encoder_join)(); bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen, const uint8_t *thumbnailbuf, int thumbnailfd, - const uint8_t *snapshotbuf, int snapshotfd); + const uint8_t *snapshotbuf, int snapshotfd, + common_crop_t *scaling_parms); int (*LINK_camframe_terminate)(void); int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality); @@ -802,9 +803,11 @@ bool QualcommCameraHardware::native_jpeg_encode ( } } + static common_crop_t scale; // no scaling if (!LINK_jpeg_encoder_encode(&mDimension, thumbnail_buf, thumb_fd, - main_img_buf, snap_fd)) { + main_img_buf, snap_fd, + &scale)) { LOGE("native_jpeg_encode: jpeg_encoder_encode failed."); return false; } @@ -1089,10 +1092,14 @@ void QualcommCameraHardware::release() LOGV("release E"); Mutex::Autolock l(&mLock); +#if DLOPEN_LIBMMCAMERA if (libmmcamera == NULL) { LOGE("ERROR: multiple release!"); return; } +#else +#warning "Cannot detect multiple release when not dlopen()ing libqcamera!" +#endif int cnt, rc; struct msm_ctrl_cmd ctrlCmd; From 105a7f6c76583dccf140654e5309905131fdab66 Mon Sep 17 00:00:00 2001 From: Chih-Chung Chang Date: Tue, 16 Jun 2009 17:15:48 +0800 Subject: [PATCH 15/29] Enable more debug message to debug the Camera startPreview bug. --- libcamera2/QualcommCameraHardware.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index ee0ac66..7778883 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -867,13 +867,13 @@ void QualcommCameraHardware::runFrameThread(void *data) void *frame_thread(void *user) { - LOGV("frame_thread E"); + LOGD("frame_thread E"); sp obj = QualcommCameraHardware::getInstance(); if (obj != 0) { obj->runFrameThread(user); } else LOGW("not starting frame thread: the object went away!"); - LOGV("frame_thread X"); + LOGD("frame_thread X"); return NULL; } @@ -1089,7 +1089,7 @@ void QualcommCameraHardware::deinitRaw() void QualcommCameraHardware::release() { - LOGV("release E"); + LOGD("release E"); Mutex::Autolock l(&mLock); #if DLOPEN_LIBMMCAMERA @@ -1141,14 +1141,14 @@ void QualcommCameraHardware::release() } #endif - LOGV("release X"); + LOGD("release X"); } QualcommCameraHardware::~QualcommCameraHardware() { - LOGV("~QualcommCameraHardware E"); + LOGD("~QualcommCameraHardware E"); singleton.clear(); - LOGV("~QualcommCameraHardware X"); + LOGD("~QualcommCameraHardware X"); } sp QualcommCameraHardware::getRawHeap() const @@ -1493,13 +1493,13 @@ wp QualcommCameraHardware::singleton; // and return it. sp QualcommCameraHardware::createInstance() { - LOGV("createInstance: E"); + LOGD("createInstance: E"); Mutex::Autolock lock(&singleton_lock); if (singleton != 0) { sp hardware = singleton.promote(); if (hardware != 0) { - LOGV("createInstance: X return existing hardware=%p", &(*hardware)); + LOGD("createInstance: X return existing hardware=%p", &(*hardware)); return hardware; } } @@ -1508,7 +1508,7 @@ sp QualcommCameraHardware::createInstance() struct stat st; int rc = stat("/dev/oncrpc", &st); if (rc < 0) { - LOGV("createInstance: X failed to create hardware: %s", strerror(errno)); + LOGD("createInstance: X failed to create hardware: %s", strerror(errno)); return NULL; } } @@ -1519,7 +1519,7 @@ sp QualcommCameraHardware::createInstance() cam->startCamera(); cam->initDefaultParameters(); - LOGV("createInstance: X created hardware=%p", &(*hardware)); + LOGD("createInstance: X created hardware=%p", &(*hardware)); return hardware; } From e610e2518d2982d579f58953267980df68f70a40 Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Tue, 16 Jun 2009 01:46:46 +0800 Subject: [PATCH 16/29] Get the values returned from CAMERA_GET_PARM_ZOOM correctly. --- libcamera2/QualcommCameraHardware.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 7778883..152ce56 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1879,7 +1879,7 @@ bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) ctrlCmd.timeout_ms = 5000; ctrlCmd.length = sizeof(cam_parm_info_t); ctrlCmd.value = pZoom; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { LOGE("native_get_zoom: ioctl fd %d error %s", @@ -1887,14 +1887,14 @@ bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) return false; } - LOGV("native_get_zoom::current val=%d max=%d min=%d step val=%d", + memcpy(pZoom, *(cam_parm_info_t **)ctrlCmd.value, sizeof(cam_parm_info_t)); + + LOGD("native_get_zoom::current val=%d max=%d min=%d step val=%d", pZoom->current_value, pZoom->maximum_value, pZoom->minimum_value, pZoom->step_value); - memcpy(pZoom, (cam_parm_info_t *)ctrlCmd.value, sizeof(cam_parm_info_t)); - return ctrlCmd.status; } From 2c2e8580d653632f7945b4d18aa804f9bb7fd237 Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Wed, 17 Jun 2009 19:03:42 +0800 Subject: [PATCH 17/29] Add picture size values and fix effect values. --- libcamera2/QualcommCameraHardware.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 152ce56..3039181 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -180,7 +180,7 @@ static char *whitebalance_values; // from camera_effect_t static const str_map color_effects[] = { - { "none", CAMERA_EFFECT_OFF }, /* This list must match aeecamera.h */ + { "off", CAMERA_EFFECT_OFF }, /* This list must match aeecamera.h */ { "mono", CAMERA_EFFECT_MONO }, { "negative", CAMERA_EFFECT_NEGATIVE }, { "solarize", CAMERA_EFFECT_SOLARIZE }, @@ -362,8 +362,9 @@ void QualcommCameraHardware::initDefaultParameters() INIT_VALUES_FOR(whitebalance); p.set("anti-banding-values", anti_banding_values); - p.set("color-effects-values", color_effects_values); + p.set("effect-values", color_effects_values); p.set("whitebalance-values", whitebalance_values); + p.set("picture-size-values", "2048x1536,1600x1200,1024x768"); // FIXME: we can specify these numeric ranges better p.set("exposure-offset-values", "0,1,2,3,4,5,6,7,8,9,10"); From 321cfafbf54977d45cecdb7d8dc464f3c512d8fe Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Fri, 19 Jun 2009 16:04:38 +0800 Subject: [PATCH 18/29] Add location to exif. --- libcamera2/QualcommCameraHardware.cpp | 51 +++++++++++++++++++++++++++ libcamera2/QualcommCameraHardware.h | 1 + 2 files changed, 52 insertions(+) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 3039181..cea73f2 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -90,6 +90,7 @@ int (*LINK_camframe_terminate)(void); int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality); int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation); +int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location); // callbacks void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame); void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, @@ -105,6 +106,7 @@ void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); #define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality #define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality #define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation +#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation extern void (*mmcamera_camframe_callback)(struct msm_frame *frame); extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); @@ -428,6 +430,9 @@ void QualcommCameraHardware::startCamera() *(void**)&LINK_jpeg_encoder_setRotation = ::dlsym(libmmcamera, "jpeg_encoder_setRotation"); + *(void**)&LINK_jpeg_encoder_setLocation = + ::dlsym(libmmcamera, "jpeg_encoder_setLocation"); + *(void **)&LINK_cam_conf = ::dlsym(libmmcamera, "cam_conf"); #else @@ -804,6 +809,8 @@ bool QualcommCameraHardware::native_jpeg_encode ( } } + jpeg_set_location(); + static common_crop_t scale; // no scaling if (!LINK_jpeg_encoder_encode(&mDimension, thumbnail_buf, thumb_fd, @@ -815,6 +822,50 @@ bool QualcommCameraHardware::native_jpeg_encode ( return true; } +void QualcommCameraHardware::jpeg_set_location() +{ + bool encode_location = true; + camera_position_type pt; + +#define PARSE_LOCATION(what,type,fmt,desc) do { \ + pt.what = 0; \ + const char *what##_str = mParameters.get("gps-"#what); \ + LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \ + if (what##_str) { \ + type what = 0; \ + if (sscanf(what##_str, fmt, &what) == 1) \ + pt.what = what; \ + else { \ + LOGE("GPS " #what " %s could not" \ + " be parsed as a " #desc, what##_str); \ + encode_location = false; \ + } \ + } \ + else { \ + LOGV("GPS " #what " not specified: " \ + "defaulting to zero in EXIF header."); \ + encode_location = false; \ + } \ + } while(0) + + PARSE_LOCATION(timestamp, long, "%ld", "long"); + if (!pt.timestamp) pt.timestamp = time(NULL); + PARSE_LOCATION(altitude, short, "%hd", "short"); + PARSE_LOCATION(latitude, double, "%lf", "double float"); + PARSE_LOCATION(longitude, double, "%lf", "double float"); + +#undef PARSE_LOCATION + + if (encode_location) { + LOGD("setting image location ALT %d LAT %lf LON %lf", + pt.altitude, pt.latitude, pt.longitude); + if (!LINK_jpeg_encoder_setLocation(&pt)) { + LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed."); + } + } + else LOGV("not setting image location"); +} + void QualcommCameraHardware::runFrameThread(void *data) { LOGV("runFrameThread E"); diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index 02fa598..a4c9dc7 100644 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -97,6 +97,7 @@ public: uint8_t * buff_ptr , uint32_t buff_size); bool previewEnabled(); + void jpeg_set_location(); private: From 3ba00f29ba317790cd3dd3131d2e1fcff00faeb2 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Tue, 23 Jun 2009 19:10:08 -0700 Subject: [PATCH 19/29] libcamera fixes -- general cleanup: made a bunch of functions static to QualcommCameraHardware.cpp, not class members; got rid of unnecessary private member variables. The only functions that remain as members are native_set_dimension() and native_jpeg_encode() -- removed kRawFrameHeaderSize; aDSP frame offsets are zero now; -- simplify reg_unreg_buf -- Removed PreviewPmemPool and RawPmemPool, which do not need to be specialized on top of PmemPool. We use PmemPool instead. -- use PmemPool to both create pmem pools and register them with the driver -- takePicture runs in a separate thread -- the destructor keeps a singleton lock -- PmemPool calls dup() on the camera-control file descriptor to guard against release() calling close() on it before PmemPool has a chance to deregister pmem from the camera driver. -- got rid of hal_mmap() and hal_munmap() entirely and created a PmemHeap to manage thumbnails. -- removed support for CAPTURE_RAW. The CameraService can already do this. Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 720 ++++++++++---------------- libcamera2/QualcommCameraHardware.h | 128 ++--- 2 files changed, 309 insertions(+), 539 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index cea73f2..3a10260 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -31,7 +31,6 @@ #endif #include -#define CAPTURE_RAW 0 #define LIKELY(exp) __builtin_expect(!!(exp), 1) #define UNLIKELY(exp) __builtin_expect(!!(exp), 0) @@ -227,61 +226,6 @@ static Mutex singleton_lock; static void receive_camframe_callback(struct msm_frame *frame); static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size); static void receive_jpeg_callback(jpeg_event_t status); -static uint8_t *hal_mmap (uint32_t size, int *pmemFd); -static int hal_munmap (int pmem_fd, void *addr, size_t size); - -static uint8_t* hal_mmap(uint32_t size, int *pmemFd) -{ - void *ret; /* returned virtual address */ - int pmem_fd = open("/dev/pmem_adsp", O_RDWR); - - if (pmem_fd < 0) { - LOGE("hal_mmap: open /dev/pmem_adsp error %s!", - strerror(errno)); - return NULL; - } - - /* to make it page size aligned */ - // FIXME: use clp2() here - size = (size + 4095) & (~4095); - - LOGV("hal_mmap: pmem_fd %d size: %d", pmem_fd, size); - - ret = mmap(NULL, - size, - PROT_READ | PROT_WRITE, - MAP_SHARED, - pmem_fd, - 0); - - if (ret == MAP_FAILED) { - LOGE("hal_mmap: pmem mmap() error %s", strerror(errno)); - close(pmem_fd); - return NULL; - } - - *pmemFd = pmem_fd; - return (uint8_t *)ret; -} - -static int hal_munmap (int pmem_fd, void *addr, size_t size) -{ - int rc; - - // FIXME: use clp2()? - size = (size + 4095) & (~4095); - - LOGV("hal_munmap pmem_fd %d, size = %d, virt_addr = 0x%x", - pmem_fd, - size, (uint32_t)addr); - - rc = munmap(addr, size); - if (rc < 0) - LOGE("hal_munmap: munmap error %s", strerror(errno)); - - close(pmem_fd); - return rc; -} QualcommCameraHardware::QualcommCameraHardware() : mParameters(), @@ -296,6 +240,7 @@ QualcommCameraHardware::QualcommCameraHardware() mCameraRunning(false), mPreviewInitialized(false), mFrameThreadRunning(false), + mSnapshotThreadRunning(false), mReleasedRecordingFrame(false), mShutterCallback(0), mRawPictureCallback(0), @@ -310,17 +255,12 @@ QualcommCameraHardware::QualcommCameraHardware() mPreviewFrameSize(0), mRawSize(0), mCameraControlFd(-1), - mPmemThumbnailFd(-1), - mPmemSnapshotFd(-1), - mPreviewFrameOffset(0), - mThumbnailBuf(NULL), - mMainImageBuf(NULL), mAutoFocusThreadRunning(false), mAutoFocusFd(-1), mInPreviewCallback(false) { memset(&mZoom, 0, sizeof(mZoom)); - memset(&mFrameThread, 0, sizeof(mFrameThread)); + memset(&mDimension, 0, sizeof(mDimension)); LOGV("constructor EX"); } @@ -336,19 +276,11 @@ void QualcommCameraHardware::initDefaultParameters() p.setPreviewFormat("yuv420sp"); // informative p.setPictureFormat("jpeg"); // informative - memset(&mDimension, 0, sizeof(mDimension)); - - mDimension.picture_width = DEFAULT_PICTURE_WIDTH; - mDimension.picture_height = DEFAULT_PICTURE_HEIGHT; - mDimension.display_width = ps->width; - mDimension.display_height = ps->height; - mDimension.ui_thumbnail_width = THUMBNAIL_WIDTH; - mDimension.ui_thumbnail_height = THUMBNAIL_HEIGHT; - p.set("jpeg-thumbnail-width", THUMBNAIL_WIDTH_STR); // informative p.set("jpeg-thumbnail-height", THUMBNAIL_HEIGHT_STR); // informative p.set("jpeg-thumbnail-quality", "90"); - p.setPictureSize(mDimension.picture_width, mDimension.picture_height); + + p.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT); #if 0 p.set("gps-timestamp", "1199145600"); // Jan 1, 2008, 00:00:00 @@ -453,7 +385,7 @@ void QualcommCameraHardware::startCamera() pthread_create(&mCamConfigThread, NULL, LINK_cam_conf, NULL); - LOGE("startCamera X"); + LOGV("startCamera X"); } status_t QualcommCameraHardware::dump(int fd, @@ -509,10 +441,11 @@ bool QualcommCameraHardware::native_set_dimension(int camfd) return false; } - return ctrlCmd.status; + LOGV("native_set_dimension status %d\n", ctrlCmd.status); + return ctrlCmd.status == CAM_CTRL_SUCCESS; } -bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) +static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) { int rc; struct msm_ctrl_cmd ctrlCmd; @@ -532,7 +465,7 @@ bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE; } -bool native_cancel_afmode(int camfd, int af_fd) +static bool native_cancel_afmode(int camfd, int af_fd) { int rc; struct msm_ctrl_cmd ctrlCmd; @@ -549,83 +482,7 @@ bool native_cancel_afmode(int camfd, int af_fd) return rc >= 0; } -void QualcommCameraHardware::reg_unreg_buf( - int camfd, - int width, - int height, - int pmempreviewfd, - uint8_t *prev_buf, - int pmem_type, - bool unregister, - bool active) -{ - uint32_t y_size; - struct msm_pmem_info pmemBuf; - uint32_t ioctl_cmd; - - if (prev_buf == NULL) - return; - - y_size = width * height; - - pmemBuf.type = pmem_type; - pmemBuf.fd = pmempreviewfd; - pmemBuf.vaddr = prev_buf; - pmemBuf.y_off = 0; - pmemBuf.cbcr_off = PAD_TO_WORD(y_size); - pmemBuf.active = active; - - ioctl_cmd = unregister ? - MSM_CAM_IOCTL_UNREGISTER_PMEM : - MSM_CAM_IOCTL_REGISTER_PMEM; - - LOGV("Entered reg_unreg_buf: camfd = %d, ioctl_cmd = %d, " - "pmemBuf.cbcr_off=%d, active=%d", - camfd, ioctl_cmd, pmemBuf.cbcr_off, active); - if (ioctl(camfd, ioctl_cmd, &pmemBuf) < 0) { - LOGE("reg_unreg_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s", - camfd, - strerror(errno)); - } -} - -bool QualcommCameraHardware::native_register_preview_bufs( - int camfd, - struct msm_frame *frame, - bool active) -{ - LOGV("mDimension.display_width = %d, display_height = %d", - mDimension.display_width, mDimension.display_height); - - reg_unreg_buf(camfd, - mDimension.display_width, - mDimension.display_height, - frame->fd, - (uint8_t *)frame->buffer, - MSM_PMEM_OUTPUT2, - false, - active); - - return true; -} - -bool QualcommCameraHardware::native_unregister_preview_bufs( - int camfd, - int pmempreviewfd, - uint8_t *prev_buf) -{ - reg_unreg_buf(camfd, - mDimension.display_width, - mDimension.display_height, - pmempreviewfd, - prev_buf, - MSM_PMEM_OUTPUT2, - true, - true); - return true; -} - -bool QualcommCameraHardware::native_start_preview(int camfd) +static bool native_start_preview(int camfd) { struct msm_ctrl_cmd ctrlCmd; @@ -644,64 +501,7 @@ bool QualcommCameraHardware::native_start_preview(int camfd) return true; } -bool QualcommCameraHardware::native_register_snapshot_bufs( - int camfd, - int pmemthumbnailfd, - int pmemsnapshotfd, - uint8_t *thumbnail_buf, - uint8_t *main_img_buf) -{ - reg_unreg_buf(camfd, - mDimension.thumbnail_width, - mDimension.thumbnail_height, - pmemthumbnailfd, - thumbnail_buf, - MSM_PMEM_THUMBAIL, - false, - true); - - /* For original snapshot*/ - reg_unreg_buf(camfd, - mDimension.orig_picture_dx, - mDimension.orig_picture_dy, - pmemsnapshotfd, - main_img_buf, - MSM_PMEM_MAINIMG, - false, - true); - return true; -} - -bool QualcommCameraHardware::native_unregister_snapshot_bufs( - int camfd, - int thumb_fd, - int snap_fd, - uint8_t *thumbnail_buf, - uint8_t *main_img_buf) -{ - reg_unreg_buf(camfd, - mDimension.thumbnail_width, - mDimension.thumbnail_height, - thumb_fd, - thumbnail_buf, - MSM_PMEM_THUMBAIL, - true, - true); - - /* For original snapshot*/ - reg_unreg_buf(camfd, - mDimension.orig_picture_dx, - mDimension.orig_picture_dy, - snap_fd, - main_img_buf, - MSM_PMEM_MAINIMG, - true, - true); - - return true; -} - -bool QualcommCameraHardware::native_get_picture (int camfd) +static bool native_get_picture (int camfd) { struct msm_ctrl_cmd ctrlCmd; @@ -718,7 +518,7 @@ bool QualcommCameraHardware::native_get_picture (int camfd) return true; } -bool QualcommCameraHardware::native_stop_preview(int camfd) +static bool native_stop_preview(int camfd) { struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; @@ -736,7 +536,7 @@ bool QualcommCameraHardware::native_stop_preview(int camfd) return true; } -bool QualcommCameraHardware::native_start_snapshot(int camfd) +static bool native_start_snapshot(int camfd) { struct msm_ctrl_cmd ctrlCmd; @@ -755,7 +555,7 @@ bool QualcommCameraHardware::native_start_snapshot(int camfd) return true; } -bool QualcommCameraHardware::native_stop_snapshot (int camfd) +static bool native_stop_snapshot (int camfd) { struct msm_ctrl_cmd ctrlCmd; @@ -774,11 +574,7 @@ bool QualcommCameraHardware::native_stop_snapshot (int camfd) return true; } -bool QualcommCameraHardware::native_jpeg_encode ( - int thumb_fd, - int snap_fd, - uint8_t *thumbnail_buf, - uint8_t *main_img_buf) +bool QualcommCameraHardware::native_jpeg_encode(void) { int jpeg_quality = mParameters.getInt("jpeg-quality"); if (jpeg_quality >= 0) { @@ -812,9 +608,12 @@ bool QualcommCameraHardware::native_jpeg_encode ( jpeg_set_location(); static common_crop_t scale; // no scaling + if (!LINK_jpeg_encoder_encode(&mDimension, - thumbnail_buf, thumb_fd, - main_img_buf, snap_fd, + (uint8_t *)mThumbnailHeap->mHeap->base(), + mThumbnailHeap->mHeap->getHeapID(), + (uint8_t *)mRawHeap->mHeap->base(), + mRawHeap->mHeap->getHeapID(), &scale)) { LOGE("native_jpeg_encode: jpeg_encoder_encode failed."); return false; @@ -888,18 +687,6 @@ void QualcommCameraHardware::runFrameThread(void *data) LINK_cam_frame(data); } - for (cnt = 0; cnt < kPreviewBufferCount; ++cnt) { - LOGV("unregisterPreviewBuf %d", cnt); - native_unregister_preview_bufs(mCameraControlFd, - frames[cnt].fd, - (uint8_t *)frames[cnt].buffer); - LOGV("do_munmap preview buffer %d, fd=%d, prev_buf=0x%lx, size=%d", - cnt, frames[cnt].fd, frames[cnt].buffer,frame_size); - int rc = hal_munmap(frames[cnt].fd, - (uint8_t *)frames[cnt].buffer,frame_size); - LOGV("do_munmap done with return value %d", rc); - } - LOGV("unregisterPreviewBuf %d", cnt); mPreviewHeap.clear(); #if DLOPEN_LIBMMCAMERA @@ -942,15 +729,24 @@ bool QualcommCameraHardware::initPreview() } mFrameThreadWaitLock.unlock(); + mSnapshotThreadWaitLock.lock(); + while (mSnapshotThreadRunning) { + LOGV("initPreview: waiting for old snapshot thread to complete."); + mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); + LOGV("initPreview: old snapshot thread completed."); + } + mSnapshotThreadWaitLock.unlock(); + int cnt = 0; mPreviewFrameSize = mPreviewWidth * mPreviewHeight * 3/2; - mPreviewHeap = - new PreviewPmemPool(kRawFrameHeaderSize + - mPreviewWidth * mPreviewHeight * 3/2, - kPreviewBufferCount, - mPreviewFrameSize, - kRawFrameHeaderSize, - "preview"); + mPreviewHeap = new PmemPool("/dev/pmem_adsp", + mCameraControlFd, + MSM_PMEM_OUTPUT2, + mPreviewFrameSize, + kPreviewBufferCount, + mPreviewFrameSize, + 0, + "preview"); if (!mPreviewHeap->initialized()) { mPreviewHeap.clear(); @@ -958,38 +754,21 @@ bool QualcommCameraHardware::initPreview() return false; } - bool ret = true; - mDimension.picture_width = DEFAULT_PICTURE_WIDTH; mDimension.picture_height = DEFAULT_PICTURE_HEIGHT; - ret = native_set_dimension(mCameraControlFd); - if(ret) { - frame_size = (clp2(mDimension.display_width * - mDimension.display_height * 3/2)); + bool ret = native_set_dimension(mCameraControlFd); + + if (ret) { for (cnt = 0; cnt < kPreviewBufferCount; cnt++) { - frames[cnt].fd = 0; + frames[cnt].fd = mPreviewHeap->mHeap->getHeapID(); frames[cnt].buffer = - (unsigned long)hal_mmap(frame_size, &(frames[cnt].fd)); + (uint32_t)mPreviewHeap->mHeap->base() + mPreviewFrameSize * cnt; frames[cnt].y_off = 0; - frames[cnt].cbcr_off = - mDimension.display_width * mDimension.display_height; - - if (frames[cnt].buffer == 0) { - LOGE("initPreview X: mmap failed!"); - return false; - } - + frames[cnt].cbcr_off = mPreviewWidth * mPreviewHeight; frames[cnt].path = MSM_FRAME_ENC; - - LOGV("do_mmap pbuf = 0x%lx, pmem_fd = %d", - frames[cnt].buffer, frames[cnt].fd); - native_register_preview_bufs(mCameraControlFd, - &frames[cnt], - cnt != kPreviewBufferCount - 1); } - mFrameThreadWaitLock.lock(); pthread_attr_t attr; pthread_attr_init(&attr); @@ -1037,68 +816,52 @@ bool QualcommCameraHardware::initRaw(bool initJpegHeap) mDimension.picture_width = mRawWidth; mDimension.picture_height = mRawHeight; + mRawSize = mRawWidth * mRawHeight * 3 / 2; + mJpegMaxSize = mRawWidth * mRawHeight * 3 / 2; if(!native_set_dimension(mCameraControlFd)) { LOGE("initRaw X: failed to set dimension"); return false; } - mRawSize = mRawWidth * mRawHeight * 3 / 2; - - mJpegMaxSize = mRawWidth * mRawHeight * 3 / 2; - - LOGE("initRaw: clearing old mJpegHeap."); - mJpegHeap.clear(); + if (mJpegHeap != NULL) { + LOGV("initRaw: clearing old mJpegHeap."); + mJpegHeap.clear(); + } // Snapshot LOGV("initRaw: initializing mRawHeap."); mRawHeap = - new RawPmemPool("/dev/pmem_camera", - kRawFrameHeaderSize + mJpegMaxSize, - kRawBufferCount, - mRawSize, - kRawFrameHeaderSize, - "snapshot camera"); + new PmemPool("/dev/pmem_camera", + mCameraControlFd, + MSM_PMEM_MAINIMG, + mJpegMaxSize, + kRawBufferCount, + mRawSize, + 0, + "snapshot camera"); if (!mRawHeap->initialized()) { LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp"); mRawHeap = - new RawPmemPool("/dev/pmem_adsp", - kRawFrameHeaderSize + mJpegMaxSize, - kRawBufferCount, - mRawSize, - kRawFrameHeaderSize, - "snapshot camera"); + new PmemPool("/dev/pmem_adsp", + mCameraControlFd, + MSM_PMEM_MAINIMG, + mJpegMaxSize, + kRawBufferCount, + mRawSize, + 0, + "snapshot camera"); if (!mRawHeap->initialized()) { - LOGE("initRaw X: error initializing mRawHeap"); mRawHeap.clear(); + LOGE("initRaw X: error initializing mRawHeap"); return false; } } - mMainImageBuf = (uint8_t *)mRawHeap->mHeap->base(); - mPmemSnapshotFd = mRawHeap->mHeap->getHeapID(); - - LOGV("do_mmap snapshot pbuf = 0x%p, pmem_fd = %d", - mMainImageBuf, mPmemSnapshotFd); - - // Thumbnails - - mThumbnailBuf = hal_mmap(THUMBNAIL_BUFFER_SIZE, &mPmemThumbnailFd); - LOGV("do_mmap thumbnail pbuf = 0x%p, pmem_fd = %d", - mThumbnailBuf, mPmemThumbnailFd); - if (mThumbnailBuf == NULL) { - mRawHeap.clear(); - LOGE("initRaw X: cannot allocate thumbnail memory"); - return false; - } - - native_register_snapshot_bufs(mCameraControlFd, - mPmemThumbnailFd, - mPmemSnapshotFd, - mThumbnailBuf, - mMainImageBuf); + LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d", + (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID()); // Jpeg @@ -1110,10 +873,31 @@ bool QualcommCameraHardware::initRaw(bool initJpegHeap) 0, // we do not know how big the picture wil be 0, "jpeg"); + if (!mJpegHeap->initialized()) { - LOGE("initRaw X failed: error initializing mJpegHeap."); mJpegHeap.clear(); mRawHeap.clear(); + LOGE("initRaw X failed: error initializing mJpegHeap."); + return false; + } + + // Thumbnails + + mThumbnailHeap = + new PmemPool("/dev/pmem_adsp", + mCameraControlFd, + MSM_PMEM_THUMBAIL, + THUMBNAIL_BUFFER_SIZE, + 1, + THUMBNAIL_BUFFER_SIZE, + 0, + "thumbnail"); + + if (!mThumbnailHeap->initialized()) { + mThumbnailHeap.clear(); + mJpegHeap.clear(); + mRawHeap.clear(); + LOGE("initRaw X failed: error initializing mThumbnailHeap."); return false; } } @@ -1125,17 +909,11 @@ bool QualcommCameraHardware::initRaw(bool initJpegHeap) void QualcommCameraHardware::deinitRaw() { LOGV("deinitRaw E"); + + mThumbnailHeap.clear(); mJpegHeap.clear(); mRawHeap.clear(); - native_unregister_snapshot_bufs(mCameraControlFd, - mPmemThumbnailFd, mPmemSnapshotFd, - mThumbnailBuf, mMainImageBuf); - - if (mThumbnailBuf) { - hal_munmap(mPmemThumbnailFd, mThumbnailBuf, THUMBNAIL_BUFFER_SIZE); - mThumbnailBuf = NULL; - } LOGV("deinitRaw X"); } @@ -1199,6 +977,7 @@ void QualcommCameraHardware::release() QualcommCameraHardware::~QualcommCameraHardware() { LOGD("~QualcommCameraHardware E"); + Mutex::Autolock lock(&singleton_lock); singleton.clear(); LOGD("~QualcommCameraHardware X"); } @@ -1405,6 +1184,34 @@ status_t QualcommCameraHardware::autoFocus(autofocus_callback af_cb, return NO_ERROR; } +void QualcommCameraHardware::runSnapshotThread(void *data) +{ + LOGV("runSnapshotThread E"); + if (native_start_snapshot(mCameraControlFd)) + receiveRawPicture(); + else + LOGE("main: native_start_snapshot failed!"); + + mSnapshotThreadWaitLock.lock(); + mSnapshotThreadRunning = false; + mSnapshotThreadWait.signal(); + mSnapshotThreadWaitLock.unlock(); + + LOGV("runSnapshotThread X"); +} + +void *snapshot_thread(void *user) +{ + LOGD("snapshot_thread E"); + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->runSnapshotThread(user); + } + else LOGW("not starting snapshot thread: the object went away!"); + LOGD("snapshot_thread X"); + return NULL; +} + status_t QualcommCameraHardware::takePicture(shutter_callback shutter_cb, raw_callback raw_cb, jpeg_callback jpeg_cb, @@ -1429,14 +1236,24 @@ status_t QualcommCameraHardware::takePicture(shutter_callback shutter_cb, mPictureCallbackCookie = user; } - if (native_start_snapshot(mCameraControlFd) == false) { - LOGE("main: start_preview failed!"); - return UNKNOWN_ERROR; + mSnapshotThreadWaitLock.lock(); + while (mSnapshotThreadRunning) { + LOGV("takePicture: waiting for old snapshot thread to complete."); + mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); + LOGV("takePicture: old snapshot thread completed."); } - receiveRawPicture(); + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + mSnapshotThreadRunning = !pthread_create(&mSnapshotThread, + &attr, + snapshot_thread, + NULL); + mSnapshotThreadWaitLock.unlock(); LOGV("takePicture: X"); - return NO_ERROR; + return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR; } status_t QualcommCameraHardware::cancelPicture( @@ -1465,33 +1282,57 @@ status_t QualcommCameraHardware::setParameters( Mutex::Autolock l(&mLock); - mParameters = params; - - int width, height; - params.getPreviewSize(&width, &height); - LOGV("requested size %d x %d", width, height); preview_size_type *ps = preview_sizes; - size_t i; - for (i = 0; i < PREVIEW_SIZE_COUNT; ++i, ++ps) { - if (width >= ps->width && height >= ps->height) - break; + + { + int width, height; + params.getPreviewSize(&width, &height); + LOGV("requested size %d x %d", width, height); + // Validate the preview size + size_t i; + for (i = 0; i < PREVIEW_SIZE_COUNT; ++i, ++ps) { + if (width == ps->width && height == ps->height) + break; + } + if (i == PREVIEW_SIZE_COUNT) { + LOGE("Invalid preview size requested: %dx%d", + width, height); + return BAD_VALUE; + } } - if (i == PREVIEW_SIZE_COUNT) - ps--; - LOGV("actual size %d x %d", ps->width, ps->height); - mParameters.setPreviewSize(ps->width, ps->height); + mPreviewWidth = mDimension.display_width = ps->width; + mPreviewHeight = mDimension.display_height = ps->height; - mDimension.display_width = ps->width; - mDimension.display_height = ps->height; + // FIXME: validate snapshot sizes, - mParameters.getPreviewSize(&mPreviewWidth, &mPreviewHeight); - mParameters.getPictureSize(&mRawWidth, &mRawHeight); + params.getPictureSize(&mRawWidth, &mRawHeight); + mDimension.picture_width = mRawWidth; + mDimension.picture_height = mRawHeight; - mPreviewWidth = (mPreviewWidth + 1) & ~1; - mPreviewHeight = (mPreviewHeight + 1) & ~1; - mRawHeight = (mRawHeight + 1) & ~1; - mRawWidth = (mRawWidth + 1) & ~1; + // Set up the jpeg-thumbnail-size parameters. + + { + int val; + + val = params.getInt("jpeg-thumbnail-width"); + if (val < 0) { + mDimension.ui_thumbnail_width= THUMBNAIL_WIDTH; + LOGW("jpeg-thumbnail-width is not specified: defaulting to %d", + THUMBNAIL_WIDTH); + } + else mDimension.ui_thumbnail_width = val; + + val = params.getInt("jpeg-thumbnail-height"); + if (val < 0) { + mDimension.ui_thumbnail_height= THUMBNAIL_HEIGHT; + LOGW("jpeg-thumbnail-height is not specified: defaulting to %d", + THUMBNAIL_HEIGHT); + } + else mDimension.ui_thumbnail_height = val; + } + + mParameters = params; if (mCameraRunning) { @@ -1588,39 +1429,6 @@ sp QualcommCameraHardware::getInstance() } } -#if CAPTURE_RAW -static void dump_to_file(const char *fname, - uint8_t *buf, uint32_t size) -{ - int nw, cnt = 0; - uint32_t written = 0; - - LOGD("opening file [%s]", fname); - int fd = open(fname, O_RDWR | O_CREAT); - if (fd < 0) { - LOGE("failed to create file [%s]: %s", fname, strerror(errno)); - return; - } - - LOGD("writing %d uint8_ts to file [%s]", size, fname); - while (written < size) { - nw = ::write(fd, - buf + written, - size - written); - if (nw < 0) { - LOGE("failed to write to file [%s]: %s", - fname, strerror(errno)); - break; - } - written += nw; - cnt++; - } - LOGD("done writing %d uint8_ts to file [%s] in %d passes", - size, fname, cnt); - ::close(fd); -} -#endif // CAMERA_RAW - void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) { // LOGV("receivePreviewFrame E"); @@ -1639,21 +1447,19 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) // Find the offset within the heap of the current buffer. ssize_t offset = - mPreviewWidth * mPreviewHeight * - mPreviewFrameOffset * 3 / 2; + (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base(); + offset /= mPreviewFrameSize; - memcpy((uint8_t *)mPreviewHeap->mHeap->base() + offset, - (uint8_t *)frame->buffer, - mPreviewWidth * mPreviewHeight * 3 / 2); + //LOGV("%d\n", offset); mInPreviewCallback = true; if (pcb != NULL) - pcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], + pcb(mPreviewHeap->mBuffers[offset], pdata); if(rcb != NULL) { Mutex::Autolock rLock(&mRecordFrameLock); - rcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], rdata); + rcb(mPreviewHeap->mBuffers[offset], rdata); if (mReleasedRecordingFrame != true) { LOGV("block for release frame request/command"); mRecordWait.wait(mRecordFrameLock); @@ -1662,9 +1468,6 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) } mInPreviewCallback = false; - mPreviewFrameOffset++; - mPreviewFrameOffset %= kPreviewBufferCount; - // LOGV("receivePreviewFrame X"); } @@ -1727,8 +1530,7 @@ bool QualcommCameraHardware::recordingEnabled() return mCameraRunning && mRecordingCallback != NULL; } -void -QualcommCameraHardware::notifyShutter() +void QualcommCameraHardware::notifyShutter() { LOGV("notifyShutter: E"); if (mShutterCallback) @@ -1736,10 +1538,7 @@ QualcommCameraHardware::notifyShutter() LOGV("notifyShutter: X"); } -static ssize_t snapshot_offset = 0; - -void -QualcommCameraHardware::receiveRawPicture() +void QualcommCameraHardware::receiveRawPicture() { LOGV("receiveRawPicture: E"); @@ -1752,12 +1551,7 @@ QualcommCameraHardware::receiveRawPicture() LOGE("getPicture failed!"); return; } - ssize_t offset = (mRawWidth * mRawHeight * snapshot_offset * 3 / 2); -#if CAPTURE_RAW - dump_to_file("/sdcard/photo.raw", - (uint8_t *)mMainImageBuf, mRawWidth * mRawHeight * 3 / 2); -#endif - mRawPictureCallback(mRawHeap->mBuffers[offset], + mRawPictureCallback(mRawHeap->mBuffers[0], mPictureCallbackCookie); } else LOGV("Raw-picture callback was canceled--skipping."); @@ -1765,10 +1559,7 @@ QualcommCameraHardware::receiveRawPicture() if (mJpegPictureCallback != NULL) { mJpegSize = 0; if (LINK_jpeg_encoder_init()) { - if(native_jpeg_encode(mPmemThumbnailFd, - mPmemSnapshotFd, - mThumbnailBuf, - mMainImageBuf)) { + if(native_jpeg_encode()) { LOGV("receiveRawPicture: X (success)"); return; } @@ -1800,8 +1591,7 @@ void QualcommCameraHardware::receiveJpegPictureFragment( mJpegSize += buff_size; } -void -QualcommCameraHardware::receiveJpegPicture(void) +void QualcommCameraHardware::receiveJpegPicture(void) { LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)", mJpegSize, mJpegHeap->mBufferSize); @@ -1923,7 +1713,7 @@ void QualcommCameraHardware::setBrightness() } } -bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) +static bool native_get_zoom(int camfd, void *pZm) { struct msm_ctrl_cmd ctrlCmd; cam_parm_info_t *pZoom = (cam_parm_info_t *)pZm; @@ -1950,7 +1740,7 @@ bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) return ctrlCmd.status; } -bool QualcommCameraHardware::native_set_zoom(int camfd, void *pZm) +static bool native_set_zoom(int camfd, void *pZm) { struct msm_ctrl_cmd ctrlCmd; @@ -2080,7 +1870,17 @@ QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers, completeInitialization(); } +static bool register_buf(int camfd, + int size, + int pmempreviewfd, + uint32_t offset, + uint8_t *buf, + int pmem_type, + bool register_buffer = true); + QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool, + int camera_control_fd, + int pmem_type, int buffer_size, int num_buffers, int frame_size, int frame_offset, @@ -2089,7 +1889,9 @@ QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool, num_buffers, frame_size, frame_offset, - name) + name), + mPmemType(pmem_type), + mCameraControlFd(dup(camera_control_fd)) { LOGV("constructing MemPool %s backed by pmem pool %s: " "%d frames @ %d bytes, offset %d, buffer size %d", @@ -2097,6 +1899,10 @@ QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool, pmem_pool, num_buffers, frame_size, frame_offset, buffer_size); + LOGV("%s: duplicating control fd %d --> %d", + __FUNCTION__, + camera_control_fd, mCameraControlFd); + // Make a new mmap'ed heap that can be shared across processes. mAlignedSize = clp2(buffer_size * num_buffers); @@ -2119,65 +1925,45 @@ QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool, return; } - LOGE("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld", + LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld", pmem_pool, mFd, mSize.len); + // Unregister preview buffers with the camera drivers. + for (int cnt = 0; cnt < num_buffers; ++cnt) { + register_buf(mCameraControlFd, + buffer_size, + mHeap->getHeapID(), + buffer_size * cnt, + (uint8_t *)mHeap->base() + buffer_size * cnt, + pmem_type); + } + completeInitialization(); } else LOGE("pmem pool %s error: could not create master heap!", pmem_pool); } -QualcommCameraHardware::PreviewPmemPool::PreviewPmemPool( - int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name) : - QualcommCameraHardware::PmemPool("/dev/pmem_adsp", - buffer_size, - num_buffers, - frame_size, - frame_offset, - name) +QualcommCameraHardware::PmemPool::~PmemPool() { - LOGV("constructing PreviewPmemPool"); -} - -QualcommCameraHardware::PreviewPmemPool::~PreviewPmemPool() -{ - LOGV("destroying PreviewPmemPool"); - if(initialized()) { - void *base = mHeap->base(); - LOGV("destroying PreviewPmemPool"); - } -} - -QualcommCameraHardware::RawPmemPool::RawPmemPool( - const char *pmem_pool, - int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name) : - QualcommCameraHardware::PmemPool(pmem_pool, - buffer_size, - num_buffers, - frame_size, - frame_offset, - name) -{ - LOGV("constructing RawPmemPool"); -} - -QualcommCameraHardware::RawPmemPool::~RawPmemPool() -{ - LOGV("destroying RawPmemPool"); - if(initialized()) { - void *base = mHeap->base(); - LOGV("releasing RawPmemPool memory %p", - base); + LOGV("%s: %s E", __FUNCTION__, mName); + // Unregister preview buffers with the camera drivers. + for (int cnt = 0; cnt < mNumBuffers; ++cnt) { + register_buf(mCameraControlFd, + mBufferSize, + mHeap->getHeapID(), + mBufferSize * cnt, + (uint8_t *)mHeap->base() + mBufferSize * cnt, + mPmemType, + false /* unregister */); } + LOGV("destroying PmemPool %s: closing control fd %d", + mName, + mCameraControlFd); + close(mCameraControlFd); + LOGV("%s: %s X", __FUNCTION__, mName); } QualcommCameraHardware::MemPool::~MemPool() @@ -2189,6 +1975,40 @@ QualcommCameraHardware::MemPool::~MemPool() LOGV("destroying MemPool %s completed", mName); } +static bool register_buf(int camfd, + int size, + int pmempreviewfd, + uint32_t offset, + uint8_t *buf, + int pmem_type, + bool register_buffer) +{ + struct msm_pmem_info pmemBuf; + + pmemBuf.type = pmem_type; + pmemBuf.fd = pmempreviewfd; + pmemBuf.offset = offset; + pmemBuf.len = size; + pmemBuf.vaddr = buf; + pmemBuf.y_off = 0; + pmemBuf.cbcr_off = PAD_TO_WORD(size * 2 / 3); + pmemBuf.active = true; + + LOGV("register_buf: camfd = %d, reg = %d buffer = %p", + camfd, !register_buffer, buf); + if (ioctl(camfd, + register_buffer ? + MSM_CAM_IOCTL_REGISTER_PMEM : + MSM_CAM_IOCTL_UNREGISTER_PMEM, + &pmemBuf) < 0) { + LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s", + camfd, + strerror(errno)); + return false; + } + return true; +} + status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector& args) const { const size_t SIZE = 256; diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index a4c9dc7..2ab2384 100644 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -36,68 +36,30 @@ public: virtual sp getPreviewHeap() const; virtual sp getRawHeap() const; - virtual status_t dump(int fd, const Vector& args) const; - virtual status_t startPreview(preview_callback cb, void* user); - virtual void stopPreview(); - virtual status_t startRecording(recording_callback cb, void* user); - virtual void stopRecording(); - virtual bool recordingEnabled(); - virtual void releaseRecordingFrame(const sp& mem); - virtual status_t autoFocus(autofocus_callback, void *user); - virtual status_t takePicture(shutter_callback, - raw_callback, - jpeg_callback, - void* user); - virtual status_t cancelPicture(bool cancel_shutter, - bool cancel_raw, bool cancel_jpeg); - virtual status_t setParameters(const CameraParameters& params); - virtual CameraParameters getParameters() const; - + virtual status_t dump(int fd, const Vector& args) const; + virtual status_t startPreview(preview_callback cb, void* user); + virtual void stopPreview(); + virtual bool previewEnabled(); + virtual status_t startRecording(recording_callback cb, void* user); + virtual void stopRecording(); + virtual bool recordingEnabled(); + virtual void releaseRecordingFrame(const sp& mem); + virtual status_t autoFocus(autofocus_callback, void *user); + virtual status_t takePicture(shutter_callback, raw_callback, + jpeg_callback, void *); + virtual status_t cancelPicture(bool cancel_shutter, + bool cancel_raw, bool cancel_jpeg); + virtual status_t setParameters(const CameraParameters& params); + virtual CameraParameters getParameters() const; virtual void release(); static sp createInstance(); static sp getInstance(); - - - bool native_set_dimension (int camfd); - void reg_unreg_buf(int camfd, int width, int height, - int pmempreviewfd, uint8_t *prev_buf, - int pmem_type, - bool unregister, - bool active); - bool native_register_preview_bufs(int camfd, - struct msm_frame *frame,bool active); - bool native_unregister_preview_bufs(int camfd, int pmempreviewfd, - uint8_t *prev_buf); - - bool native_start_preview(int camfd); - bool native_stop_preview(int camfd); - - bool native_register_snapshot_bufs(int camfd, int pmemthumbnailfd, - int pmemsnapshotfd, - uint8_t *thumbnail_buf, - uint8_t *main_img_buf); - bool native_unregister_snapshot_bufs(int camfd, int pmemThumbnailfd, - int pmemSnapshotfd, - uint8_t *thumbnail_buf, - uint8_t *main_img_buf); - bool native_get_picture(int camfd); - bool native_start_snapshot(int camfd); - bool native_stop_snapshot(int camfd); - bool native_jpeg_encode (int pmemThumbnailfd, int pmemSnapshotfd, - uint8_t *thumbnail_buf, uint8_t *main_img_buf); - - bool native_set_zoom(int camfd, void *pZm); - bool native_get_zoom(int camfd, void *pZm); - void receivePreviewFrame(struct msm_frame *frame); void receiveJpegPicture(void); - void receiveJpegPictureFragment( - uint8_t * buff_ptr , uint32_t buff_size); - bool previewEnabled(); - void jpeg_set_location(); + void receiveJpegPictureFragment(uint8_t *buf, uint32_t size); private: @@ -108,6 +70,8 @@ private: friend void *auto_focus_thread(void *user); void runAutoFocus(); void cancelAutoFocus(); + bool native_set_dimension (int camfd); + bool native_jpeg_encode (void); static wp singleton; @@ -118,7 +82,6 @@ private: static const int kPreviewBufferCount = 4; static const int kRawBufferCount = 1; static const int kJpegBufferCount = 1; - static const int kRawFrameHeaderSize = 0; //TODO: put the picture dimensions in the CameraParameters object; CameraParameters mParameters; @@ -133,7 +96,7 @@ private: bool mZoomInitialised; bool mCameraRunning; bool mPreviewInitialized; - + // This class represents a heap which maintains several contiguous // buffers. The heap may be backed by pmem (when pmem_pool contains // the name of a /dev/pmem* file), or by ashmem (when pmem_pool == NULL). @@ -147,7 +110,7 @@ private: virtual ~MemPool() = 0; void completeInitialization(); - bool initialized() const { + bool initialized() const { return mHeap != NULL && mHeap->base() != MAP_FAILED; } @@ -172,37 +135,23 @@ private: struct PmemPool : public MemPool { PmemPool(const char *pmem_pool, - int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name); - virtual ~PmemPool(){ } + int control_camera_fd, int pmem_type, + int buffer_size, int num_buffers, + int frame_size, int frame_offset, + const char *name); + virtual ~PmemPool(); int mFd; + int mPmemType; + int mCameraControlFd; uint32_t mAlignedSize; struct pmem_region mSize; }; - struct PreviewPmemPool : public PmemPool { - virtual ~PreviewPmemPool(); - PreviewPmemPool(int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name); - }; - - struct RawPmemPool : public PmemPool { - virtual ~RawPmemPool(); - RawPmemPool(const char *pmem_pool, - int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name); - }; - - sp mPreviewHeap; - sp mRawHeap; + sp mPreviewHeap; + sp mThumbnailHeap; + sp mRawHeap; sp mJpegHeap; - + void startCamera(); bool initPreview(); void deinitPreview(); @@ -215,6 +164,12 @@ private: friend void *frame_thread(void *user); void runFrameThread(void *data); + bool mSnapshotThreadRunning; + Mutex mSnapshotThreadWaitLock; + Condition mSnapshotThreadWait; + friend void *snapshot_thread(void *user); + void runSnapshotThread(void *data); + void initDefaultParameters(); void setSensorPreviewEffect(int, const char*); @@ -227,7 +182,7 @@ private: bool mReleasedRecordingFrame; void notifyShutter(); - + void receiveRawPicture(void); Mutex mCallbackLock; @@ -241,7 +196,6 @@ private: zero, or the size of the last JPEG picture taken. */ uint32_t mJpegSize; - shutter_callback mShutterCallback; raw_callback mRawPictureCallback; @@ -266,17 +220,13 @@ private: int mCameraControlFd; cam_parm_info_t mZoom; cam_ctrl_dimension_t mDimension; - int mPmemThumbnailFd; - int mPmemSnapshotFd; - ssize_t mPreviewFrameOffset; - uint8_t *mThumbnailBuf; - uint8_t *mMainImageBuf; bool mAutoFocusThreadRunning; Mutex mAutoFocusThreadLock; int mAutoFocusFd; pthread_t mCamConfigThread; pthread_t mFrameThread; + pthread_t mSnapshotThread; struct msm_frame frames[kPreviewBufferCount]; bool mInPreviewCallback; From 9db8a0fc2669c73018122887b88c523e14f404d7 Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Thu, 25 Jun 2009 16:48:11 +0800 Subject: [PATCH 20/29] Add preview size 384x288. --- libcamera2/QualcommCameraHardware.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 3a10260..212b3f0 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -123,6 +123,7 @@ static preview_size_type preview_sizes[] = { { 800, 480 }, // WVGA { 640, 480 }, // VGA { 480, 320 }, // HVGA + { 384, 288 }, { 352, 288 }, // CIF { 320, 240 }, // QVGA { 240, 160 }, // SQVGA From 3c05a4483c4c5f9eba830fb3b626d97a68c0d4a2 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Mon, 29 Jun 2009 13:09:24 -0700 Subject: [PATCH 21/29] libcamera: dlopen() libqcamera in the AF thread Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 212b3f0..c5ca2cf 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -678,7 +678,7 @@ void QualcommCameraHardware::runFrameThread(void *data) // lifetime of this object. We do not want to dlclose() libqcamera while // LINK_cam_frame is still running. void *libhandle = ::dlopen("libqcamera.so", RTLD_NOW); - LOGV("loading libqcamera at %p", libhandle); + LOGV("FRAME: loading libqcamera at %p", libhandle); if (!libhandle) { LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); } @@ -1097,6 +1097,23 @@ void QualcommCameraHardware::runAutoFocus() return; } +#if DLOPEN_LIBMMCAMERA + // We need to maintain a reference to libqcamera.so for the duration of the + // AF thread, because we do not know when it will exit relative to the + // lifetime of this object. We do not want to dlclose() libqcamera while + // LINK_cam_frame is still running. + void *libhandle = ::dlopen("libqcamera.so", RTLD_NOW); + LOGV("AF: loading libqcamera at %p", libhandle); + if (!libhandle) { + LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); + close(mAutoFocusFd); + mAutoFocusFd = -1; + mAutoFocusThreadRunning = false; + mAutoFocusThreadLock.unlock(); + return; + } +#endif + /* This will block until either AF completes or is cancelled. */ LOGV("af start (fd %d)", mAutoFocusFd); bool status = native_set_afmode(mAutoFocusFd, AF_MODE_AUTO); @@ -1117,6 +1134,13 @@ void QualcommCameraHardware::runAutoFocus() mAutoFocusCallback = NULL; mAutoFocusCallbackCookie = NULL; mCallbackLock.unlock(); + +#if DLOPEN_LIBMMCAMERA + if (libhandle) { + ::dlclose(libhandle); + LOGV("AF: dlclose(libqcamera)"); + } +#endif } void QualcommCameraHardware::cancelAutoFocus() From ad48d0f0807349dd0f8e8a584411f738d9cd2155 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Tue, 30 Jun 2009 16:07:21 -0700 Subject: [PATCH 22/29] libcamera: set antibanding to 60Hz, use cropping information on snapshot -- Set the antibanding to 60Hz for the US (Should be 50Hz for the rest of the world.) -- Save the cropping info returned when taking a picture and then pass it to the JPEG encoder. This enables digital zoom for JPEG images (cropping and upsampling). Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 26 +++++++++++++++++++------- libcamera2/QualcommCameraHardware.h | 2 ++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index c5ca2cf..00ef2fa 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -262,6 +262,7 @@ QualcommCameraHardware::QualcommCameraHardware() { memset(&mZoom, 0, sizeof(mZoom)); memset(&mDimension, 0, sizeof(mDimension)); + memset(&mCrop, 0, sizeof(mCrop)); LOGV("constructor EX"); } @@ -502,12 +503,13 @@ static bool native_start_preview(int camfd) return true; } -static bool native_get_picture (int camfd) +static bool native_get_picture (int camfd, common_crop_t *crop) { struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; - ctrlCmd.length = 0; + ctrlCmd.length = sizeof(common_crop_t); + ctrlCmd.value = crop; if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) { LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s", @@ -516,6 +518,18 @@ static bool native_get_picture (int camfd) return false; } + LOGV("crop: in1_w %d", crop->in1_w); + LOGV("crop: in1_h %d", crop->in1_h); + LOGV("crop: out1_w %d", crop->out1_w); + LOGV("crop: out1_h %d", crop->out1_h); + + LOGV("crop: in2_w %d", crop->in2_w); + LOGV("crop: in2_h %d", crop->in2_h); + LOGV("crop: out2_w %d", crop->out2_w); + LOGV("crop: out2_h %d", crop->out2_h); + + LOGV("crop: update %d", crop->update_flag); + return true; } @@ -608,14 +622,12 @@ bool QualcommCameraHardware::native_jpeg_encode(void) jpeg_set_location(); - static common_crop_t scale; // no scaling - if (!LINK_jpeg_encoder_encode(&mDimension, (uint8_t *)mThumbnailHeap->mHeap->base(), mThumbnailHeap->mHeap->getHeapID(), (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID(), - &scale)) { + &mCrop)) { LOGE("native_jpeg_encode: jpeg_encoder_encode failed."); return false; } @@ -1572,7 +1584,7 @@ void QualcommCameraHardware::receiveRawPicture() Mutex::Autolock cbLock(&mCallbackLock); notifyShutter(); if (mRawPictureCallback != NULL) { - if(native_get_picture(mCameraControlFd)== false) { + if(native_get_picture(mCameraControlFd, &mCrop)== false) { LOGE("getPicture failed!"); return; } @@ -1700,7 +1712,7 @@ void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) antibandvalue = attr_lookup(anti_banding, antibanding, - CAMERA_ANTIBANDING_OFF); + CAMERA_ANTIBANDING_60HZ); ctrlCmd.value = (void *)&antibandvalue; LOGV("In setAntiBanding: match: %s: %d", antibanding, antibandvalue); diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index 2ab2384..1a55132 100644 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -228,6 +228,8 @@ private: pthread_t mFrameThread; pthread_t mSnapshotThread; + common_crop_t mCrop; + struct msm_frame frames[kPreviewBufferCount]; bool mInPreviewCallback; }; From 04b2c40f3c18177563dc54175e02ee042ae3ddae Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Mon, 22 Jun 2009 23:23:37 +0800 Subject: [PATCH 23/29] Change the timing of shutter callback. --- libcamera2/QualcommCameraHardware.cpp | 24 ++++++++++++++++++++---- libcamera2/QualcommCameraHardware.h | 3 +-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 00ef2fa..e8c67dd 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -95,6 +95,7 @@ void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame); void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); +void (**LINK_mmcamera_shutter_callback)(); #else #define LINK_cam_conf cam_conf #define LINK_cam_frame cam_frame @@ -110,6 +111,7 @@ extern void (*mmcamera_camframe_callback)(struct msm_frame *frame); extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); extern void (*mmcamera_jpeg_callback)(jpeg_event_t status); +extern void (*mmcamera_shutter_callback)(); #endif } // extern "C" @@ -227,6 +229,7 @@ static Mutex singleton_lock; static void receive_camframe_callback(struct msm_frame *frame); static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size); static void receive_jpeg_callback(jpeg_event_t status); +static void receive_shutter_callback(); QualcommCameraHardware::QualcommCameraHardware() : mParameters(), @@ -355,6 +358,11 @@ void QualcommCameraHardware::startCamera() *LINK_mmcamera_jpeg_callback = receive_jpeg_callback; + *(void **)&LINK_mmcamera_shutter_callback = + ::dlsym(libmmcamera, "mmcamera_shutter_callback"); + + *LINK_mmcamera_shutter_callback = receive_shutter_callback; + *(void**)&LINK_jpeg_encoder_setMainImageQuality = ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality"); @@ -373,6 +381,7 @@ void QualcommCameraHardware::startCamera() mmcamera_camframe_callback = receive_camframe_callback; mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback; mmcamera_jpeg_callback = receive_jpeg_callback; + mmcamera_shutter_callback = receive_shutter_callback; #endif // DLOPEN_LIBMMCAMERA /* The control thread is in libcamera itself. */ @@ -1569,10 +1578,18 @@ bool QualcommCameraHardware::recordingEnabled() void QualcommCameraHardware::notifyShutter() { - LOGV("notifyShutter: E"); if (mShutterCallback) mShutterCallback(mPictureCallbackCookie); - LOGV("notifyShutter: X"); +} + +static void receive_shutter_callback() +{ + LOGV("receive_shutter_callback: E"); + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->notifyShutter(); + } + LOGV("receive_shutter_callback: X"); } void QualcommCameraHardware::receiveRawPicture() @@ -1580,9 +1597,8 @@ void QualcommCameraHardware::receiveRawPicture() LOGV("receiveRawPicture: E"); int ret,rc,rete; -// Temporary fix for multiple snapshot issue on 8k: disabling shutter callback + Mutex::Autolock cbLock(&mCallbackLock); - notifyShutter(); if (mRawPictureCallback != NULL) { if(native_get_picture(mCameraControlFd, &mCrop)== false) { LOGE("getPicture failed!"); diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index 1a55132..c647fcd 100644 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -60,6 +60,7 @@ public: void receiveJpegPicture(void); void jpeg_set_location(); void receiveJpegPictureFragment(uint8_t *buf, uint32_t size); + void notifyShutter(); private: @@ -181,8 +182,6 @@ private: Mutex mLock; bool mReleasedRecordingFrame; - void notifyShutter(); - void receiveRawPicture(void); Mutex mCallbackLock; From 12b41c417f901fc76d985ff51c2525284635e74e Mon Sep 17 00:00:00 2001 From: Dave Sparks Date: Wed, 8 Jul 2009 15:58:41 -0700 Subject: [PATCH 24/29] Add timestamps to video frames to improve A/V sync. Bug 1927069. --- libcamera2/QualcommCameraHardware.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index e8c67dd..37cf953 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1505,7 +1505,7 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) if(rcb != NULL) { Mutex::Autolock rLock(&mRecordFrameLock); - rcb(mPreviewHeap->mBuffers[offset], rdata); + rcb(systemTime(), mPreviewHeap->mBuffers[offset], rdata); if (mReleasedRecordingFrame != true) { LOGV("block for release frame request/command"); mRecordWait.wait(mRecordFrameLock); From dbdbc0d26cc9744ae0cc86b85d893e81cc14373e Mon Sep 17 00:00:00 2001 From: James Dong Date: Fri, 10 Jul 2009 17:20:16 -0700 Subject: [PATCH 25/29] The antibanding (60Hz) broke the bar code scanner. bug 1962986 --- libcamera2/QualcommCameraHardware.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 37cf953..9a3555b 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1728,7 +1728,13 @@ void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) antibandvalue = attr_lookup(anti_banding, antibanding, - CAMERA_ANTIBANDING_60HZ); + /* FIXME: + * CAMERA_ANTIBANDING_60HZ broke the barcode scanner + * somehow. turn it off and revert it back to off + * for now until we figure out what is the best + * solution. + */ + CAMERA_ANTIBANDING_OFF /*CAMERA_ANTIBANDING_60HZ */); ctrlCmd.value = (void *)&antibandvalue; LOGV("In setAntiBanding: match: %s: %d", antibanding, antibandvalue); From bb05604b8de9bed83d937148a056eba256dd9e2b Mon Sep 17 00:00:00 2001 From: Chih-Chung Chang Date: Mon, 13 Jul 2009 19:29:25 +0800 Subject: [PATCH 26/29] Fix 1956740: startPreview failed The problem is even after release() is done, the singleton variable is not cleared, so a new openCameraHardware() call could return an instance which is already released. The singleton variable is cleared in the destructor, so we wait until that happens in openCameraHardware(). --- libcamera2/QualcommCameraHardware.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 9a3555b..1679133 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -225,6 +225,8 @@ static inline unsigned clp2(unsigned x) namespace android { static Mutex singleton_lock; +static bool singleton_releasing; +static Condition singleton_wait; static void receive_camframe_callback(struct msm_frame *frame); static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size); @@ -993,6 +995,9 @@ void QualcommCameraHardware::release() } #endif + Mutex::Autolock lock(&singleton_lock); + singleton_releasing = true; + LOGD("release X"); } @@ -1001,6 +1006,8 @@ QualcommCameraHardware::~QualcommCameraHardware() LOGD("~QualcommCameraHardware E"); Mutex::Autolock lock(&singleton_lock); singleton.clear(); + singleton_releasing = false; + singleton_wait.signal(); LOGD("~QualcommCameraHardware X"); } @@ -1435,6 +1442,13 @@ sp QualcommCameraHardware::createInstance() LOGD("createInstance: E"); Mutex::Autolock lock(&singleton_lock); + + // Wait until the previous release is done. + while (singleton_releasing) { + LOGD("Wait for previous release."); + singleton_wait.wait(singleton_lock); + } + if (singleton != 0) { sp hardware = singleton.promote(); if (hardware != 0) { From bcb33e4db815d828f71715bc12fbe33b191045aa Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Wed, 15 Jul 2009 15:58:21 +0800 Subject: [PATCH 27/29] 1. Remove the zoom and brightness. 2. Set default value of antibanding, effect, and white-balance at initialization. 3. Do not set the parameter if it is not found. --- libcamera2/QualcommCameraHardware.cpp | 348 ++++++-------------------- libcamera2/QualcommCameraHardware.h | 22 +- 2 files changed, 88 insertions(+), 282 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 1679133..fe9007a 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -67,12 +67,9 @@ extern "C" { #define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2) #define DEFAULT_PREVIEW_SETTING 2 // HVGA -#define MAX_ZOOM_STEPS 6 #define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(preview_size_type)) -#define BRIGHTNESS_MAX 10 // FIXME: this should correlate with brightness-values -#define BRIGHTNESS_DEF 5 // FIXME: this should correlate with brightness-values -#define ZOOM_MAX 10 // FIXME: this should correlate with zoom-values +#define NOT_FOUND -1 #if DLOPEN_LIBMMCAMERA #include @@ -132,14 +129,7 @@ static preview_size_type preview_sizes[] = { { 176, 144 }, // QCIF }; -struct str_map { - const char *const desc; - int val; -}; - -static int attr_lookup(const struct str_map *const arr, - const char *name, - int def) +static int attr_lookup(const struct str_map *const arr, const char *name) { if (name) { const struct str_map *trav = arr; @@ -149,7 +139,7 @@ static int attr_lookup(const struct str_map *const arr, trav++; } } - return def; + return NOT_FOUND; } #define INIT_VALUES_FOR(parm) do { \ @@ -183,7 +173,7 @@ static const str_map whitebalance[] = { static char *whitebalance_values; // from camera_effect_t -static const str_map color_effects[] = { +static const str_map effect[] = { { "off", CAMERA_EFFECT_OFF }, /* This list must match aeecamera.h */ { "mono", CAMERA_EFFECT_MONO }, { "negative", CAMERA_EFFECT_NEGATIVE }, @@ -198,17 +188,17 @@ static const str_map color_effects[] = { { "aqua", CAMERA_EFFECT_AQUA }, { NULL, 0 } }; -static char *color_effects_values; +static char *effect_values; // from qcamera/common/camera.h -static const str_map anti_banding[] = { +static const str_map antibanding[] = { { "off", CAMERA_ANTIBANDING_OFF }, { "60hz", CAMERA_ANTIBANDING_60HZ }, { "50hz", CAMERA_ANTIBANDING_50HZ }, { "auto", CAMERA_ANTIBANDING_AUTO }, { NULL, 0 } }; -static char *anti_banding_values; +static char *antibanding_values; // round to the next power of two static inline unsigned clp2(unsigned x) @@ -239,10 +229,6 @@ QualcommCameraHardware::QualcommCameraHardware() mPreviewWidth(-1), mRawHeight(-1), mRawWidth(-1), - mBrightness(BRIGHTNESS_DEF), - mZoomValuePrev(0), - mZoomValueCurr(0), - mZoomInitialised(false), mCameraRunning(false), mPreviewInitialized(false), mFrameThreadRunning(false), @@ -265,7 +251,6 @@ QualcommCameraHardware::QualcommCameraHardware() mAutoFocusFd(-1), mInPreviewCallback(false) { - memset(&mZoom, 0, sizeof(mZoom)); memset(&mDimension, 0, sizeof(mDimension)); memset(&mCrop, 0, sizeof(mCrop)); LOGV("constructor EX"); @@ -288,6 +273,15 @@ void QualcommCameraHardware::initDefaultParameters() p.set("jpeg-thumbnail-quality", "90"); p.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT); + p.set("antibanding", + /* FIXME: + * CAMERA_ANTIBANDING_60HZ broke the barcode scanner somehow. turn it + * off and revert it back to off for now until we figure out what is + * the best solution. + */ + "off" /*"60hz" */); + p.set("effect", "off"); + p.set("whitebalance", "auto"); #if 0 p.set("gps-timestamp", "1199145600"); // Jan 1, 2008, 00:00:00 @@ -298,19 +292,15 @@ void QualcommCameraHardware::initDefaultParameters() // This will happen only one in the lifetime of the mediaserver process. // We do not free the _values arrays when we destroy the camera object. - INIT_VALUES_FOR(anti_banding); - INIT_VALUES_FOR(color_effects); + INIT_VALUES_FOR(antibanding); + INIT_VALUES_FOR(effect); INIT_VALUES_FOR(whitebalance); - p.set("anti-banding-values", anti_banding_values); - p.set("effect-values", color_effects_values); + p.set("antibanding-values", antibanding_values); + p.set("effect-values", effect_values); p.set("whitebalance-values", whitebalance_values); p.set("picture-size-values", "2048x1536,1600x1200,1024x768"); - // FIXME: we can specify these numeric ranges better - p.set("exposure-offset-values", "0,1,2,3,4,5,6,7,8,9,10"); - p.set("zoom-values", "0,1,2,3,4,5,6,7,8,9,10"); - if (setParameters(p) != NO_ERROR) { LOGE("Failed to set default parameters?!"); } @@ -437,27 +427,6 @@ status_t QualcommCameraHardware::dump(int fd, return NO_ERROR; } -bool QualcommCameraHardware::native_set_dimension(int camfd) -{ - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.type = CAMERA_SET_PARM_DIMENSION; - ctrlCmd.timeout_ms = 5000; - ctrlCmd.length = sizeof(cam_ctrl_dimension_t); - ctrlCmd.value = &mDimension; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_set_dimension: ioctl fd %d error %s", - camfd, - strerror(errno)); - return false; - } - - LOGV("native_set_dimension status %d\n", ctrlCmd.status); - return ctrlCmd.status == CAM_CTRL_SUCCESS; -} - static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) { int rc; @@ -645,6 +614,36 @@ bool QualcommCameraHardware::native_jpeg_encode(void) return true; } +bool QualcommCameraHardware::native_set_dimension(cam_ctrl_dimension_t *value) +{ + return native_set_parm(CAMERA_SET_PARM_DIMENSION, + sizeof(cam_ctrl_dimension_t), value); +} + +bool QualcommCameraHardware::native_set_parm( + cam_ctrl_type type, uint16_t length, void *value) +{ + int rc = true; + struct msm_ctrl_cmd ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = (uint16_t)type; + ctrlCmd.length = length; + // FIXME: this will be put in by the kernel + ctrlCmd.resp_fd = mCameraControlFd; + ctrlCmd.value = value; + + LOGV("native_set_parm. camfd=%d, type=%d, length=%d", + mCameraControlFd, type, length); + rc = ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd); + if(rc < 0 || ctrlCmd.status != CAM_CTRL_SUCCESS) { + LOGE("ioctl error. camfd=%d, type=%d, length=%d, rc=%d, ctrlCmd.status=%d, %s", + mCameraControlFd, type, length, rc, ctrlCmd.status, strerror(errno)); + return false; + } + return true; +} + void QualcommCameraHardware::jpeg_set_location() { bool encode_location = true; @@ -781,7 +780,7 @@ bool QualcommCameraHardware::initPreview() mDimension.picture_width = DEFAULT_PICTURE_WIDTH; mDimension.picture_height = DEFAULT_PICTURE_HEIGHT; - bool ret = native_set_dimension(mCameraControlFd); + bool ret = native_set_dimension(&mDimension); if (ret) { for (cnt = 0; cnt < kPreviewBufferCount; cnt++) { @@ -843,7 +842,7 @@ bool QualcommCameraHardware::initRaw(bool initJpegHeap) mRawSize = mRawWidth * mRawHeight * 3 / 2; mJpegMaxSize = mRawWidth * mRawHeight * 3 / 2; - if(!native_set_dimension(mCameraControlFd)) { + if(!native_set_dimension(&mDimension)) { LOGE("initRaw X: failed to set dimension"); return false; } @@ -1046,12 +1045,6 @@ status_t QualcommCameraHardware::startPreviewInternal() return UNKNOWN_ERROR; } - setSensorPreviewEffect(mCameraControlFd, mParameters.get("effect")); - setSensorWBLighting(mCameraControlFd, mParameters.get("whitebalance")); - setAntiBanding(mCameraControlFd, mParameters.get("antibanding")); - setBrightness(); - // FIXME: set nightshot, luma adaptatiom, zoom and check ranges - LOGV("startPreview X"); return NO_ERROR; } @@ -1335,8 +1328,8 @@ status_t QualcommCameraHardware::setParameters( Mutex::Autolock l(&mLock); + // Set preview size. preview_size_type *ps = preview_sizes; - { int width, height; params.getPreviewSize(&width, &height); @@ -1353,18 +1346,15 @@ status_t QualcommCameraHardware::setParameters( return BAD_VALUE; } } - mPreviewWidth = mDimension.display_width = ps->width; mPreviewHeight = mDimension.display_height = ps->height; // FIXME: validate snapshot sizes, - params.getPictureSize(&mRawWidth, &mRawHeight); mDimension.picture_width = mRawWidth; mDimension.picture_height = mRawHeight; // Set up the jpeg-thumbnail-size parameters. - { int val; @@ -1387,34 +1377,10 @@ status_t QualcommCameraHardware::setParameters( mParameters = params; - if (mCameraRunning) - { - setBrightness(); - - mZoomValueCurr = mParameters.getInt("zoom"); - if(mZoomValueCurr >= 0 && mZoomValueCurr <= ZOOM_MAX && - mZoomValuePrev != mZoomValueCurr) - { - bool ZoomDirectionIn = true; - if(mZoomValuePrev > mZoomValueCurr) - { - ZoomDirectionIn = false; - } - else - { - ZoomDirectionIn = true; - } - LOGV("new zoom value: %d direction = %s", - mZoomValueCurr, (ZoomDirectionIn ? "in" : "out")); - mZoomValuePrev = mZoomValueCurr; - performZoom(ZoomDirectionIn); - } - - setSensorPreviewEffect(mCameraControlFd, mParameters.get("effect")); - setSensorWBLighting(mCameraControlFd, mParameters.get("whitebalance")); - setAntiBanding(mCameraControlFd, mParameters.get("antibanding")); - // FIXME: set nightshot, luma adaptatiom, zoom and check ranges - } + setAntibanding(); + setEffect(); + setWhiteBalance(); + // FIXME: set nightshot and luma adaptatiom LOGV("setParameters: X"); return NO_ERROR ; @@ -1693,198 +1659,38 @@ bool QualcommCameraHardware::previewEnabled() return mCameraRunning && mPreviewCallback != NULL; } -void QualcommCameraHardware::setSensorPreviewEffect(int camfd, const char *effect) +int QualcommCameraHardware::getParm( + const char *parm_str, const struct str_map *const parm_map) { - LOGV("In setSensorPreviewEffect..."); - int effectsValue = 1; - struct msm_ctrl_cmd ctrlCmd; + // Check if the parameter exists. + const char *str = mParameters.get(parm_str); + if (str == NULL) return NOT_FOUND; - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_SET_PARM_EFFECT; - ctrlCmd.length = sizeof(uint32_t); - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - effectsValue = attr_lookup(color_effects, effect, CAMERA_EFFECT_OFF); - ctrlCmd.value = (void *)&effectsValue; - LOGV("In setSensorPreviewEffect, color effect match %s %d", - effect, effectsValue); - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) - LOGE("setSensorPreviewEffect fd %d error %s", camfd, strerror(errno)); + // Look up the parameter value. + return attr_lookup(parm_map, str); } -void QualcommCameraHardware::setSensorWBLighting(int camfd, const char *lighting) +void QualcommCameraHardware::setEffect() { - int lightingValue = 1; - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_SET_PARM_WB; - ctrlCmd.length = sizeof(uint32_t); - lightingValue = attr_lookup(whitebalance, lighting, CAMERA_WB_AUTO); - ctrlCmd.value = (void *)&lightingValue; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - LOGV("In setSensorWBLighting: match: %s: %d", - lighting, lightingValue); - if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) - LOGE("setSensorWBLighting: ioctl fd %d error %s", - camfd, strerror(errno)); + int32_t value = getParm("effect", effect); + if (value != NOT_FOUND) { + native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value), (void *)&value); + } } -void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) +void QualcommCameraHardware::setWhiteBalance() { - int antibandvalue = 0; - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_SET_PARM_ANTIBANDING; - ctrlCmd.length = sizeof(int32_t); - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - antibandvalue = attr_lookup(anti_banding, - antibanding, - /* FIXME: - * CAMERA_ANTIBANDING_60HZ broke the barcode scanner - * somehow. turn it off and revert it back to off - * for now until we figure out what is the best - * solution. - */ - CAMERA_ANTIBANDING_OFF /*CAMERA_ANTIBANDING_60HZ */); - ctrlCmd.value = (void *)&antibandvalue; - LOGV("In setAntiBanding: match: %s: %d", - antibanding, antibandvalue); - - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) - LOGE("setAntiBanding: ioctl %d error %s", - camfd, strerror(errno)); -} - -void QualcommCameraHardware::setBrightness() -{ - int val = mParameters.getInt("exposure-offset"); - if (val < 0) - val = BRIGHTNESS_DEF; - else if (val > BRIGHTNESS_MAX) - val = BRIGHTNESS_MAX; - - if (mBrightness != val) { - LOGV("new brightness value %d", val); - mBrightness = val; - - struct msm_ctrl_cmd ctrlCmd; - LOGV("In setBrightness: %d", val); - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_SET_PARM_BRIGHTNESS; - ctrlCmd.length = sizeof(int); - ctrlCmd.value = (void *)&val; - // FIXME: this will be put in by the kernel - ctrlCmd.resp_fd = mCameraControlFd; - - if(ioctl(mCameraControlFd, - MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) - LOGE("setBrightness: ioctl fd %d error %s", - mCameraControlFd, strerror(errno)); + int32_t value = getParm("whitebalance", whitebalance); + if (value != NOT_FOUND) { + native_set_parm(CAMERA_SET_PARM_WB, sizeof(value), (void *)&value); } } -static bool native_get_zoom(int camfd, void *pZm) +void QualcommCameraHardware::setAntibanding() { - struct msm_ctrl_cmd ctrlCmd; - cam_parm_info_t *pZoom = (cam_parm_info_t *)pZm; - ctrlCmd.type = CAMERA_GET_PARM_ZOOM; - ctrlCmd.timeout_ms = 5000; - ctrlCmd.length = sizeof(cam_parm_info_t); - ctrlCmd.value = pZoom; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_get_zoom: ioctl fd %d error %s", - camfd, strerror(errno)); - return false; - } - - memcpy(pZoom, *(cam_parm_info_t **)ctrlCmd.value, sizeof(cam_parm_info_t)); - - LOGD("native_get_zoom::current val=%d max=%d min=%d step val=%d", - pZoom->current_value, - pZoom->maximum_value, - pZoom->minimum_value, - pZoom->step_value); - - return ctrlCmd.status; -} - -static bool native_set_zoom(int camfd, void *pZm) -{ - struct msm_ctrl_cmd ctrlCmd; - - int32_t *pZoom = (int32_t *)pZm; - - ctrlCmd.type = CAMERA_SET_PARM_ZOOM; - ctrlCmd.timeout_ms = 5000; - ctrlCmd.length = sizeof(int32_t); - ctrlCmd.value = pZoom; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_set_zoom: ioctl fd %d error %s", - camfd, strerror(errno)); - return false; - } - - memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t)); - return ctrlCmd.status; -} - -void QualcommCameraHardware::performZoom(bool ZoomDir) -{ - if(mZoomInitialised == false) { - native_get_zoom(mCameraControlFd, (void *)&mZoom); - if(mZoom.maximum_value != 0) { - mZoomInitialised = true; - mZoom.step_value = (int) (mZoom.maximum_value/MAX_ZOOM_STEPS); - if( mZoom.step_value > 3 ) - mZoom.step_value = 3; - } - } - - if (ZoomDir) { - LOGV("performZoom::got zoom value of %d %d %d zoom in", - mZoom.current_value, - mZoom.step_value, - mZoom.maximum_value); - if((mZoom.current_value + mZoom.step_value) < mZoom.maximum_value) { - mZoom.current_value += mZoom.step_value; - LOGV("performZoom::Setting Zoom value of %d ",mZoom.current_value); - native_set_zoom(mCameraControlFd, (void *)&mZoom.current_value); - } - else { - LOGV("performZoom::not able to zoom in %d %d %d", - mZoom.current_value, - mZoom.step_value, - mZoom.maximum_value); - } - } - else - { - LOGV("performZoom::got zoom value of %d %d %d zoom out", - mZoom.current_value, - mZoom.step_value, - mZoom.minimum_value); - if((mZoom.current_value - mZoom.step_value) >= mZoom.minimum_value) - { - mZoom.current_value -= mZoom.step_value; - LOGV("performZoom::setting zoom value of %d ", - mZoom.current_value); - native_set_zoom(mCameraControlFd, (void *)&mZoom.current_value); - } - else - { - LOGV("performZoom::not able to zoom out %d %d %d", - mZoom.current_value, - mZoom.step_value, - mZoom.maximum_value); - } - } + camera_antibanding_type value = + (camera_antibanding_type) getParm("antibanding", antibanding); + native_set_parm(CAMERA_SET_PARM_ANTIBANDING, sizeof(value), (void *)&value); } QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers, diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index c647fcd..5f63abc 100644 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -28,6 +28,11 @@ extern "C" { #include } +struct str_map { + const char *const desc; + int val; +}; + namespace android { class QualcommCameraHardware : public CameraHardwareInterface { @@ -63,7 +68,6 @@ public: void notifyShutter(); private: - QualcommCameraHardware(); virtual ~QualcommCameraHardware(); status_t startPreviewInternal(); @@ -73,6 +77,9 @@ private: void cancelAutoFocus(); bool native_set_dimension (int camfd); bool native_jpeg_encode (void); + bool native_set_parm(cam_ctrl_type type, uint16_t length, void *value); + bool native_set_dimension(cam_ctrl_dimension_t *value); + int getParm(const char *parm_str, const str_map *parm_map); static wp singleton; @@ -91,10 +98,6 @@ private: int mRawHeight; int mRawWidth; unsigned int frame_size; - int mBrightness; - int mZoomValuePrev; - int mZoomValueCurr; - bool mZoomInitialised; bool mCameraRunning; bool mPreviewInitialized; @@ -173,11 +176,9 @@ private: void initDefaultParameters(); - void setSensorPreviewEffect(int, const char*); - void setSensorWBLighting(int, const char*); - void setAntiBanding(int, const char*); - void setBrightness(void); - void performZoom(bool); + void setAntibanding(); + void setEffect(); + void setWhiteBalance(); Mutex mLock; bool mReleasedRecordingFrame; @@ -217,7 +218,6 @@ private: #endif int mCameraControlFd; - cam_parm_info_t mZoom; cam_ctrl_dimension_t mDimension; bool mAutoFocusThreadRunning; Mutex mAutoFocusThreadLock; From 3e4574a18707e412880269bb596c2cbd8d1d6d42 Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Mon, 20 Jul 2009 14:37:26 +0800 Subject: [PATCH 28/29] Remove unsupported white balance and effect options. --- libcamera2/QualcommCameraHardware.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index fe9007a..247e24e 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -161,7 +161,6 @@ static int attr_lookup(const struct str_map *const arr, const char *name) // from aeecamera.h static const str_map whitebalance[] = { { "auto", CAMERA_WB_AUTO }, - { "custom", CAMERA_WB_CUSTOM }, { "incandescent", CAMERA_WB_INCANDESCENT }, { "florescent", CAMERA_WB_FLUORESCENT }, { "daylight", CAMERA_WB_DAYLIGHT }, @@ -178,9 +177,6 @@ static const str_map effect[] = { { "mono", CAMERA_EFFECT_MONO }, { "negative", CAMERA_EFFECT_NEGATIVE }, { "solarize", CAMERA_EFFECT_SOLARIZE }, - { "pastel", CAMERA_EFFECT_PASTEL }, - { "mosaic", CAMERA_EFFECT_MOSAIC }, - { "resize", CAMERA_EFFECT_RESIZE }, { "sepia", CAMERA_EFFECT_SEPIA }, { "postersize", CAMERA_EFFECT_POSTERIZE }, { "whiteboard", CAMERA_EFFECT_WHITEBOARD }, From a21ec0f3d3a1300f6ef07ac4c388a4025beaca30 Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Tue, 21 Jul 2009 12:28:45 +0800 Subject: [PATCH 29/29] Make sure shutter callback is called before raw callback. --- libcamera2/QualcommCameraHardware.cpp | 32 ++++++++++++++++++--------- libcamera2/QualcommCameraHardware.h | 3 +++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 247e24e..2c820a1 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1263,6 +1263,14 @@ status_t QualcommCameraHardware::takePicture(shutter_callback shutter_cb, raw_cb, jpeg_cb); Mutex::Autolock l(&mLock); + // Wait for old snapshot thread to complete. + mSnapshotThreadWaitLock.lock(); + while (mSnapshotThreadRunning) { + LOGV("takePicture: waiting for old snapshot thread to complete."); + mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); + LOGV("takePicture: old snapshot thread completed."); + } + stopPreviewInternal(); if (!initRaw(jpeg_cb != NULL)) { @@ -1278,12 +1286,9 @@ status_t QualcommCameraHardware::takePicture(shutter_callback shutter_cb, mPictureCallbackCookie = user; } - mSnapshotThreadWaitLock.lock(); - while (mSnapshotThreadRunning) { - LOGV("takePicture: waiting for old snapshot thread to complete."); - mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); - LOGV("takePicture: old snapshot thread completed."); - } + mShutterLock.lock(); + mShutterPending = true; + mShutterLock.unlock(); pthread_attr_t attr; pthread_attr_init(&attr); @@ -1554,8 +1559,12 @@ bool QualcommCameraHardware::recordingEnabled() void QualcommCameraHardware::notifyShutter() { - if (mShutterCallback) + mShutterLock.lock(); + if (mShutterPending && mShutterCallback) { mShutterCallback(mPictureCallbackCookie); + mShutterPending = false; + } + mShutterLock.unlock(); } static void receive_shutter_callback() @@ -1572,14 +1581,17 @@ void QualcommCameraHardware::receiveRawPicture() { LOGV("receiveRawPicture: E"); - int ret,rc,rete; - Mutex::Autolock cbLock(&mCallbackLock); + if (mRawPictureCallback != NULL) { - if(native_get_picture(mCameraControlFd, &mCrop)== false) { + if(native_get_picture(mCameraControlFd, &mCrop) == false) { LOGE("getPicture failed!"); return; } + + // By the time native_get_picture returns, picture is taken. Call + // shutter callback if cam config thread has not done that. + notifyShutter(); mRawPictureCallback(mRawHeap->mBuffers[0], mPictureCallbackCookie); } diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index 5f63abc..a4fe43b 100644 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -168,6 +168,9 @@ private: friend void *frame_thread(void *user); void runFrameThread(void *data); + bool mShutterPending; + Mutex mShutterLock; + bool mSnapshotThreadRunning; Mutex mSnapshotThreadWaitLock; Condition mSnapshotThreadWait;