Skip to content

Commit

Permalink
zeppelin: libcamera: improve camera zoom functionality
Browse files Browse the repository at this point in the history
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
turl committed Jul 13, 2011
1 parent e7c4647 commit 01d90d8
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 7 deletions.
84 changes: 77 additions & 7 deletions libcamera/QualcommCameraHardware.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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); \
Expand Down Expand Up @@ -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)
{
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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?!");
Expand Down Expand Up @@ -1112,6 +1145,8 @@ bool QualcommCameraHardware::initPreview()
}
mSnapshotThreadWaitLock.unlock();

setZoom();

mPreviewFrameSize = mPreviewWidth * mPreviewHeight * 3/2;
mPreviewHeap = new PreviewPmemPool(mCameraControlFd,
mPreviewWidth * mPreviewHeight * 2,
Expand Down Expand Up @@ -1642,8 +1677,6 @@ status_t QualcommCameraHardware::takePicture()
NULL);
mSnapshotThreadWaitLock.unlock();

setZoom();

LOGV("takePicture: X");
return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
}
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -2031,19 +2081,39 @@ 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);
//maxZoom/5 in the ideal world, but it's stuck on 90
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;
Expand Down
6 changes: 6 additions & 0 deletions libcamera/QualcommCameraHardware.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 01d90d8

Please sign in to comment.