Skip to content
Browse files

zeppelin: libcamera: improve camera zoom functionality

Previously you would have to lower the camera resolution in order to
zoom. This is because the zooming ability depends on the camera
resolution (lower resolution => higher zooming capability).
With this commit, when the user zooms the resolution is automatically
handled by libcamera; it is lowered when needed and goes up as the
user pans back.

Only minor drawback: the resolution on the Camera.apk options
panel is not updated as libcamera changes it.

Change-Id: I8a4b7c74f86a89f479c865e7cb1cb4217a36de7f
  • Loading branch information...
1 parent e7c4647 commit 01d90d8eef7289b5a55bed89a3a44e889a80518e @turl committed
Showing with 83 additions and 7 deletions.
  1. +77 −7 libcamera/QualcommCameraHardware.cpp
  2. +6 −0 libcamera/QualcommCameraHardware.h
View
84 libcamera/QualcommCameraHardware.cpp
@@ -121,12 +121,25 @@ 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); \
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); \
@@ -208,6 +221,21 @@ static const str_map picturesize[] = {
static char *picturesize_values;
+static const dstr_map reducesize[] = {
+ { "2560x1920", "2048x1536" },
+ { "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)
{
@@ -233,6 +261,7 @@ static int fd_frame;
//Zoom
static int32_t mMaxZoom = -1;
static bool zoomSupported = false;
+static int32_t prevzoom = 0;
struct msm_frame_t *frameA;
bool bFramePresent;
pthread_t w_thread;
@@ -309,11 +338,15 @@ 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(flashmode);
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);
@@ -325,8 +358,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, 11);
+ p.set(CameraParameters::KEY_ZOOM_RATIOS, "100,150,175,200,225,250,275,300,325,350,375,400");
if (setParameters(p) != NO_ERROR) {
LOGE("Failed to set default parameters?!");
@@ -1112,6 +1145,8 @@ bool QualcommCameraHardware::initPreview()
}
mSnapshotThreadWaitLock.unlock();
+ setZoom();
+
mPreviewFrameSize = mPreviewWidth * mPreviewHeight * 3/2;
mPreviewHeap = new PreviewPmemPool(mCameraControlFd,
mPreviewWidth * mPreviewHeight * 2,
@@ -1642,8 +1677,6 @@ status_t QualcommCameraHardware::takePicture()
NULL);
mSnapshotThreadWaitLock.unlock();
- setZoom();
-
LOGV("takePicture: X");
return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
}
@@ -1727,6 +1760,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;
@@ -2004,6 +2043,17 @@ 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);
@@ -2031,6 +2081,8 @@ void QualcommCameraHardware::setZoom()
{
int32_t level;
int32_t multiplier;
+ int32_t zoomsel;
+ bool iscamcorder = false;
if(native_get_maxzoom(mCameraControlFd,
(void *)&mMaxZoom) == true){
LOGD("Maximum zoom value is %d", mMaxZoom);
@@ -2038,12 +2090,30 @@ void QualcommCameraHardware::setZoom()
multiplier = getParm("picture-size", picturesize);
//Camcorder mode uses preview size
- if (strcmp(mParameters.get("preview-frame-rate"),"15") != 0)
+ if (strcmp(mParameters.get("preview-frame-rate"),"15") != 0){
multiplier = getParm("preview-size", picturesize);
+ iscamcorder = true;
+ }
zoomSupported = true;
if(mMaxZoom > 0){
- level = mParameters.getInt(CameraParameters::KEY_ZOOM) * multiplier;
+ //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){
+ //Reducing zoom => increasing quality
+ mParameters.set("picture-size", "2560x1920");
+ 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)/11 : 5);
}
} else {
zoomSupported = false;
View
6 libcamera/QualcommCameraHardware.h
@@ -149,6 +149,11 @@ struct str_map {
int val;
};
+struct dstr_map {
+ const char *const desc;
+ const char *const val;
+};
+
// ********************************************************************************************************
typedef unsigned int exif_tag_id_t;
@@ -266,6 +271,7 @@ class QualcommCameraHardware : public CameraHardwareInterface {
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;

0 comments on commit 01d90d8

Please sign in to comment.
Something went wrong with that request. Please try again.