From d19a116748cb53a8c9737f4aaaa506b33e969728 Mon Sep 17 00:00:00 2001 From: KalimochoAz Date: Thu, 14 Jul 2011 21:37:22 +0200 Subject: [PATCH] Implement better zoom management using Turl technique for motorola. Now zoom works without the need to change manualy the picture resolution. Added more stability to the camera and more speed Change-Id: I8ed79708391c976408ad13cfd3a4c601947d5e7b --- libcamera/QualcommCameraHardware.cpp | 134 ++++++++++++++++++++++----- libcamera/QualcommCameraHardware.h | 8 +- 2 files changed, 118 insertions(+), 24 deletions(-) diff --git a/libcamera/QualcommCameraHardware.cpp b/libcamera/QualcommCameraHardware.cpp index abec21f..6198158 100644 --- a/libcamera/QualcommCameraHardware.cpp +++ b/libcamera/QualcommCameraHardware.cpp @@ -13,7 +13,8 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ -#define REVISION_C "CM.7.1.0." +// NOTE: Version number of the lib +#define REVISION_C "CM.7.1.0.14." // #define LOG_NDEBUG 0 #define LOG_TAG "QualcommCameraHardware" @@ -120,12 +121,26 @@ static int attr_lookup(const struct str_map *const arr, const char *name) return NOT_FOUND; } +static const char* attr_lookup(const struct dstr_map *const arr, const char *name) +{ + if (name) { + const struct dstr_map *trav = arr; + while (trav->desc) { + if (!strcmp(trav->desc, name)) + return trav->val; + trav++; + } + } + return '\0'; +} + #define INIT_VALUES_FOR(parm) do { \ if (!parm##_values) { \ parm##_values = (char *)malloc(sizeof(parm)/ \ sizeof(parm[0])*30); \ + LOGD("Kalim Param: %s",parm##_values); \ char *ptr = parm##_values; \ - const str_map *trav; \ + const TYPESTRMAP *trav; \ for (trav = parm; trav->desc; trav++) { \ int len = strlen(trav->desc); \ strcpy(ptr, trav->desc); \ @@ -181,6 +196,21 @@ static const str_map picturesize[] = { }; static char *picturesize_values; +static const dstr_map reducesize[] = { + { "2048x1536", "1600x1200" }, + { "1600x1200", "1280x960" }, + { "1280x960" , "480x320" }, + { "640x480" , "320x240" }, + { "480x320" , "640x480" }, + { "320x240" , "352x288" }, + { "352x288" , "176x144" }, + { "176x144" , NULL }, + { NULL, 0 } +}; + +static char *reducesize_values; + + // round to the next power of two static inline unsigned clp2(unsigned x) { @@ -204,6 +234,7 @@ static void receive_camframe_callback(struct msm_frame_t *frame); static int camerafd; static int fd_frame; static int32_t mMaxZoom = -1; +static int32_t prevzoom = 0; static int ZOOM_STEP; static bool zoomSupported = false; struct msm_frame_t *frameA; @@ -309,10 +340,14 @@ void QualcommCameraHardware::initDefaultParameters() // This will happen only once in the lifetime of the mediaserver process. // We do not free the _values arrays when we destroy the camera object. + #define TYPESTRMAP str_map INIT_VALUES_FOR(antibanding); INIT_VALUES_FOR(effect); INIT_VALUES_FOR(whitebalance); INIT_VALUES_FOR(picturesize); + #undef TYPESTRMAP + #define TYPESTRMAP dstr_map + INIT_VALUES_FOR(reducesize); p.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING, antibanding_values); p.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values); @@ -326,8 +361,8 @@ void QualcommCameraHardware::initDefaultParameters() // Zoom parameters p.set(CameraParameters::KEY_ZOOM_SUPPORTED, "true"); p.set(CameraParameters::KEY_ZOOM, "0"); - p.set(CameraParameters::KEY_MAX_ZOOM, 5); - p.set(CameraParameters::KEY_ZOOM_RATIOS, "100,150,175,200,250,300"); + p.set(CameraParameters::KEY_MAX_ZOOM,6); + p.set(CameraParameters::KEY_ZOOM_RATIOS, "100,150,175,200,250,275,300"); if (setParameters(p) != NO_ERROR) { LOGE("Failed to set default parameters?!"); @@ -756,10 +791,7 @@ static void *cam_frame_click(void *data) timeout.tv_usec = 0; ret = select(fd_frame+1, &readfds, NULL, NULL, &timeout); - if (ret == -1) { - LOGE("calling select failed!"); - break; - } else if (FD_ISSET(fd_frame, &readfds)) { + if (FD_ISSET(fd_frame, &readfds)) { pthread_mutex_lock(&mutex_camframe); // ready to get frame ret = ioctl(fd_frame, MSM_CAM_IOCTL_GETFRAME, frameA); @@ -772,6 +804,9 @@ static void *cam_frame_click(void *data) } else LOGE("MSM_CAM_IOCTL_GETFRAME error %s", strerror(errno)); pthread_mutex_unlock(&mutex_camframe); + } else if (ret == -1) { + LOGE("calling select() failed!"); + break; } else { LOGV("frame is not ready! select returns %d", ret); usleep(100000); @@ -1015,6 +1050,8 @@ bool QualcommCameraHardware::initPreview() } mSnapshotThreadWaitLock.unlock(); + setZoom(); + mPreviewFrameSize = mPreviewWidth * mPreviewHeight * 3/2; mPreviewHeap = new PreviewPmemPool(mCameraControlFd, mPreviewWidth * mPreviewHeight * 2, @@ -1282,8 +1319,12 @@ void QualcommCameraHardware::release() libmmcamera_target = NULL; } + // FIXME: solve end of lib sometimes can fail Mutex::Autolock lock(&singleton_lock); singleton_releasing = true; + singleton.clear(); + singleton_releasing = false; + singleton_wait.signal(); LOGV("release X"); } @@ -1607,6 +1648,12 @@ status_t QualcommCameraHardware::setParameters( else mDimension.ui_thumbnail_height = val; } + //User changed pic size, recheck zoom + if (params.get("picture-size") != NULL && mParameters.get("picture-size") != NULL && strcmp(params.get("picture-size"), mParameters.get("picture-size")) != 0){ + prevzoom = 99; + LOGV("setParameters: user/system modified pic size! rechecking zoom"); + } + // setParameters mParameters = params; @@ -1699,9 +1746,7 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame_t *frame) } // Find the offset within the heap of the current buffer. - ssize_t offset = - (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base(); - offset /= mPreviewFrameSize; + ssize_t offset = 0; mInPreviewCallback = true; if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) @@ -1882,6 +1927,18 @@ int QualcommCameraHardware::getParm( return attr_lookup(parm_map, str); } +const char* QualcommCameraHardware::getParm( + const char *parm_str, const struct dstr_map *const parm_map) +{ + // Check if the parameter exists. + const char *str = mParameters.get(parm_str); + if (str == NULL) return '\0'; + + // Look up the parameter value. + return attr_lookup(parm_map, str); +} + + void QualcommCameraHardware::setEffect() { int32_t value = getParm(CameraParameters::KEY_EFFECT, effect); @@ -1917,22 +1974,48 @@ void QualcommCameraHardware::setAntibanding() void QualcommCameraHardware::setZoom() { - int32_t level = mParameters.getInt(CameraParameters::KEY_ZOOM); - + int32_t level; + int32_t multiplier; + int32_t zoomsel; + bool iscamcorder = false; + // NOTE: ZOOM Routine + LOGV(" *************************** ZOOM ROUTINE STARTED ****************************************************************************"); if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){ - LOGD("Maximum zoom value is %d", mMaxZoom); + LOGV("Maximum zoom value is %d", mMaxZoom); + //maxZoom/5 in the ideal world, but it's stuck on 90 + multiplier = getParm("picture-size", picturesize); + + LOGV("Multiplier: %d",multiplier); + + //Camcorder mode uses preview size + LOGD("preview-frame-rate: %s",mParameters.get("preview-frame-rate")); + if (strcmp(mParameters.get("preview-frame-rate"),"30") != 0){ + multiplier = getParm("preview-size", picturesize); + iscamcorder = true; + LOGV("Multiplier: %d",multiplier); + } + LOGV("Multiplier: %d, PrevZoom: %d",multiplier,prevzoom); + zoomSupported = true; if(mMaxZoom > 0){ - //if max zoom is available find the zoom ratios - int16_t * zoomRatios = new int16_t[mMaxZoom+1]; - if(zoomRatios == NULL){ - LOGE("Failed to get zoomratios..."); - delete zoomRatios; - } else { - LOGV("zoom ratios set"); + //To get more 'natural' zoom we reduce picture resolution + //if the sensor can't cope with it + zoomsel = mParameters.getInt(CameraParameters::KEY_ZOOM); + + if(!iscamcorder && prevzoom > zoomsel){ + mParameters.set("picture-size", "2048x1536"); + LOGV("User panning, increasing picture quality to max"); } + prevzoom = zoomsel; + while(!iscamcorder && zoomsel * 5 > 5 * multiplier && getParm("picture-size", reducesize) != NULL) { + mParameters.set("picture-size", getParm("picture-size", reducesize)); + multiplier = getParm("picture-size", picturesize); + LOGV("Reducing picture quality; new multiplier: %d", multiplier); + } + level = zoomsel * (iscamcorder ? (multiplier*5)/6 : 5); + LOGV("Level: %d, Multiplier: %d ZoomSel: %d",level,multiplier,zoomsel); } } else { zoomSupported = false; @@ -1941,24 +2024,29 @@ void QualcommCameraHardware::setZoom() mMaxZoom = 0; } - if (level > mMaxZoom) { + if (level >= mMaxZoom) { level = mMaxZoom; + LOGV("Level=Maxzoom: %d",level); } LOGV("Set Zoom level: %d current: %d maximum: %d", level, mCurZoom, mMaxZoom); if (level == mCurZoom) { + LOGV("Level=Curzoom: %d",level); + LOGV(" *************************** ZOOM ROUTINE ENDED ******************************************************************************"); return; } if (level != -1) { - level*=ZOOM_STEP; LOGV("Final Zoom Level: %d", level); if (level >= 0 && level <= mMaxZoom) { native_set_parm(CAMERA_SET_PARM_ZOOM, sizeof(level), (void *)&level); + usleep(35000); mCurZoom = level; } } + LOGV(" *************************** ZOOM ROUTINE ENDED ******************************************************************************"); + } QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers, diff --git a/libcamera/QualcommCameraHardware.h b/libcamera/QualcommCameraHardware.h index 78d5e61..988ab82 100644 --- a/libcamera/QualcommCameraHardware.h +++ b/libcamera/QualcommCameraHardware.h @@ -33,7 +33,7 @@ extern "C" { #define CAM_CTRL_SUCCESS 1 -#define REVISION_H "2" +#define REVISION_H "3" #define CAMERA_SET_PARM_DIMENSION 1 #define CAMERA_SET_PARM_ZOOM 2 @@ -144,6 +144,11 @@ struct str_map { int val; }; +struct dstr_map { + const char *const desc; + const char *const val; +}; + // ******************************************************************************************************** typedef unsigned int exif_tag_id_t; @@ -261,6 +266,7 @@ private: 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); + const char* getParm(const char *parm_str, const dstr_map *parm_map); void setGpsParameters(); const char *KEY_GPS_LATITUDE;