Bug 808030 - Make camera default to smallest non-0x0 thumbnail size with reduced quality. r=cjones

This commit is contained in:
Mike Habicher 2012-11-02 19:53:40 -04:00
parent 8333f28936
commit 854c16fccb
3 changed files with 133 additions and 14 deletions

View File

@ -77,6 +77,9 @@ enum {
CAMERA_PARAM_FOCUSDISTANCEOPTIMUM,
CAMERA_PARAM_FOCUSDISTANCEFAR,
CAMERA_PARAM_EXPOSURECOMPENSATION,
CAMERA_PARAM_THUMBNAILWIDTH,
CAMERA_PARAM_THUMBNAILHEIGHT,
CAMERA_PARAM_THUMBNAILQUALITY,
CAMERA_PARAM_SUPPORTED_PREVIEWSIZES,
CAMERA_PARAM_SUPPORTED_VIDEOSIZES,
@ -93,7 +96,8 @@ enum {
CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION,
CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP,
CAMERA_PARAM_SUPPORTED_ZOOM,
CAMERA_PARAM_SUPPORTED_ZOOMRATIOS
CAMERA_PARAM_SUPPORTED_ZOOMRATIOS,
CAMERA_PARAM_SUPPORTED_JPEG_THUMBNAIL_SIZES
};
#ifdef PR_LOGGING

View File

@ -29,6 +29,7 @@
#include "nsThread.h"
#include <media/MediaProfiles.h>
#include "mozilla/FileUtils.h"
#include "nsAlgorithm.h"
#include <media/mediaplayer.h>
#include "nsDirectoryServiceDefs.h" // for NS_GetSpecialDirectory
#include "nsPrintfCString.h"
@ -72,6 +73,13 @@ static const char* getKeyText(uint32_t aKey)
return CameraParameters::KEY_FOCUS_DISTANCES;
case CAMERA_PARAM_EXPOSURECOMPENSATION:
return CameraParameters::KEY_EXPOSURE_COMPENSATION;
case CAMERA_PARAM_THUMBNAILWIDTH:
return CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH;
case CAMERA_PARAM_THUMBNAILHEIGHT:
return CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT;
case CAMERA_PARAM_THUMBNAILQUALITY:
return CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY;
case CAMERA_PARAM_SUPPORTED_PREVIEWSIZES:
return CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES;
case CAMERA_PARAM_SUPPORTED_VIDEOSIZES:
@ -104,6 +112,8 @@ static const char* getKeyText(uint32_t aKey)
return CameraParameters::KEY_ZOOM_SUPPORTED;
case CAMERA_PARAM_SUPPORTED_ZOOMRATIOS:
return CameraParameters::KEY_ZOOM_RATIOS;
case CAMERA_PARAM_SUPPORTED_JPEG_THUMBNAIL_SIZES:
return CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES;
default:
return nullptr;
}
@ -174,6 +184,8 @@ nsGonkCameraControl::nsGonkCameraControl(uint32_t aCameraId, nsIThread* aCameraT
, mDeferConfigUpdate(false)
, mWidth(0)
, mHeight(0)
, mLastPictureWidth(0)
, mLastPictureHeight(0)
, mFormat(PREVIEW_FORMAT_UNKNOWN)
, mFps(30)
, mDiscardedFrameCount(0)
@ -208,6 +220,7 @@ nsGonkCameraControl::Init()
const char* const BAD_PREVIEW_FORMAT = "yuv420sp";
mParams.setPreviewFormat(PREVIEW_FORMAT);
mParams.setPreviewFrameRate(mFps);
PushParametersImpl();
// Check that our settings stuck
PullParametersImpl();
@ -402,14 +415,50 @@ nsGonkCameraControl::GetParameter(uint32_t aKey, nsTArray<CameraRegion>& aRegion
r = aRegions.AppendElement();
if (sscanf(p, "(%d,%d,%d,%d,%u)", &r->top, &r->left, &r->bottom, &r->right, &r->weight) != 5) {
DOM_CAMERA_LOGE("%s:%d : region tuple has bad format: '%s'\n", __func__, __LINE__, p);
goto GetParameter_error;
aRegions.Clear();
return;
}
}
return;
}
GetParameter_error:
aRegions.Clear();
void
nsGonkCameraControl::GetParameter(uint32_t aKey, nsTArray<CameraSize>& aSizes)
{
const char* key = getKeyText(aKey);
if (!key) {
return;
}
RwAutoLockRead lock(mRwLock);
const char* value = mParams.get(key);
DOM_CAMERA_LOGI("key='%s' --> value='%s'\n", key, value);
if (!value) {
return;
}
const char* p = value;
CameraSize* s;
// The 'value' string is in the format "w1xh1,w2xh2,w3xh3,..."
while (p) {
s = aSizes.AppendElement();
if (sscanf(p, "%dx%d", &s->width, &s->height) != 2) {
DOM_CAMERA_LOGE("%s:%d : size tuple has bad format: '%s'\n", __func__, __LINE__, p);
aSizes.Clear();
return;
}
// Look for the next record...
p = strchr(p, ',');
if (p) {
// ...skip the comma too
++p;
}
}
return;
}
nsresult
@ -524,6 +573,20 @@ nsGonkCameraControl::SetParameter(uint32_t aKey, const nsTArray<CameraRegion>& a
PushParameters();
}
void
nsGonkCameraControl::SetParameter(uint32_t aKey, int aValue)
{
const char* key = getKeyText(aKey);
if (!key) {
return;
}
{
RwAutoLockWrite lock(mRwLock);
mParams.set(key, aValue);
}
PushParameters();
}
nsresult
nsGonkCameraControl::GetPreviewStreamImpl(GetPreviewStreamTask* aGetPreviewStream)
{
@ -615,6 +678,45 @@ nsGonkCameraControl::AutoFocusImpl(AutoFocusTask* aAutoFocus)
return NS_OK;
}
void
nsGonkCameraControl::SetupThumbnail(uint32_t aPictureWidth, uint32_t aPictureHeight, uint32_t aPercentQuality)
{
/**
* Use the smallest non-0x0 thumbnail size that matches
* the aspect ratio of our parameters...
*/
uint32_t smallestArea = UINT_MAX;
uint32_t smallestIndex = UINT_MAX;
nsAutoTArray<CameraSize, 8> thumbnailSizes;
GetParameter(CAMERA_PARAM_SUPPORTED_JPEG_THUMBNAIL_SIZES, thumbnailSizes);
for (uint32_t i = 0; i < thumbnailSizes.Length(); ++i) {
uint32_t area = thumbnailSizes[i].width * thumbnailSizes[i].height;
if (area != 0
&& area < smallestArea
&& thumbnailSizes[i].width * aPictureHeight / thumbnailSizes[i].height == aPictureWidth
) {
smallestArea = area;
smallestIndex = i;
}
}
aPercentQuality = clamped<uint32_t>(aPercentQuality, 1, 100);
SetParameter(CAMERA_PARAM_THUMBNAILQUALITY, static_cast<int>(aPercentQuality));
if (smallestIndex != UINT_MAX) {
uint32_t w = thumbnailSizes[smallestIndex].width;
uint32_t h = thumbnailSizes[smallestIndex].height;
DOM_CAMERA_LOGI("Using thumbnail size: %ux%u, quality: %u %%\n", w, h, aPercentQuality);
if (w > INT_MAX || h > INT_MAX) {
DOM_CAMERA_LOGE("Thumbnail dimension is too big, will use defaults\n");
return;
}
SetParameter(CAMERA_PARAM_THUMBNAILWIDTH, static_cast<int>(w));
SetParameter(CAMERA_PARAM_THUMBNAILHEIGHT, static_cast<int>(h));
}
}
nsresult
nsGonkCameraControl::TakePictureImpl(TakePictureTask* aTakePicture)
{
@ -641,16 +743,24 @@ nsGonkCameraControl::TakePictureImpl(TakePictureTask* aTakePicture)
// batch-update camera configuration
mDeferConfigUpdate = true;
/**
* height and width: some drivers are less friendly about getting one of
* these set to zero, so if either is not specified, ignore both and go
* with current or default settings.
*/
if (aTakePicture->mSize.width && aTakePicture->mSize.height) {
nsCString s;
s.AppendPrintf("%dx%d", aTakePicture->mSize.width, aTakePicture->mSize.height);
DOM_CAMERA_LOGI("setting picture size to '%s'\n", s.get());
SetParameter(CameraParameters::KEY_PICTURE_SIZE, s.get());
if (aTakePicture->mSize.width != mLastPictureWidth || aTakePicture->mSize.height != mLastPictureHeight) {
/**
* height and width: some drivers are less friendly about getting one of
* these set to zero, so if either is not specified, ignore both and go
* with current or default settings.
*/
if (aTakePicture->mSize.width && aTakePicture->mSize.height) {
nsCString s;
s.AppendPrintf("%ux%u", aTakePicture->mSize.width, aTakePicture->mSize.height);
DOM_CAMERA_LOGI("setting picture size to '%s'\n", s.get());
SetParameter(CameraParameters::KEY_PICTURE_SIZE, s.get());
// Choose an appropriate thumbnail size and quality (from 1..100)
SetupThumbnail(aTakePicture->mSize.width, aTakePicture->mSize.height, 60);
}
mLastPictureWidth = aTakePicture->mSize.width;
mLastPictureHeight = aTakePicture->mSize.height;
}
// Picture format -- need to keep it for the callback.

View File

@ -47,10 +47,12 @@ public:
const char* GetParameterConstChar(uint32_t aKey);
double GetParameterDouble(uint32_t aKey);
void GetParameter(uint32_t aKey, nsTArray<dom::CameraRegion>& aRegions);
void GetParameter(uint32_t aKey, nsTArray<CameraSize>& aSizes);
void SetParameter(const char* aKey, const char* aValue);
void SetParameter(uint32_t aKey, const char* aValue);
void SetParameter(uint32_t aKey, double aValue);
void SetParameter(uint32_t aKey, const nsTArray<dom::CameraRegion>& aRegions);
void SetParameter(uint32_t aKey, int aValue);
nsresult GetVideoSizes(nsTArray<CameraSize>& aVideoSizes);
nsresult PushParameters();
@ -79,6 +81,7 @@ protected:
already_AddRefed<GonkRecorderProfileManager> GetGonkRecorderProfileManager();
void SetPreviewSize(uint32_t aWidth, uint32_t aHeight);
void SetupThumbnail(uint32_t aPictureWidth, uint32_t aPictureHeight, uint32_t aPercentQuality);
uint32_t mHwHandle;
double mExposureCompensationMin;
@ -88,6 +91,8 @@ protected:
android::CameraParameters mParams;
uint32_t mWidth;
uint32_t mHeight;
uint32_t mLastPictureWidth;
uint32_t mLastPictureHeight;
enum {
PREVIEW_FORMAT_UNKNOWN,