зеркало из https://github.com/mozilla/gecko-dev.git
Bug 808030 - Make camera default to smallest non-0x0 thumbnail size with reduced quality. r=cjones, a=blocking-basecamp
This commit is contained in:
Родитель
74311ae613
Коммит
ca3983720e
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче