Bug 980484 - make the zoom setting more robust, r=dhylands

This commit is contained in:
Mike Habicher 2014-03-07 01:07:27 -05:00
parent bd1cc81444
commit 0c41a3a68c
3 changed files with 56 additions and 34 deletions

View File

@ -200,11 +200,26 @@ GonkCameraParameters::Initialize()
NS_WARNING("Failed to initialize exposure compensation step size");
mExposureCompensationStep = 0;
}
rv = GetListAsArray(CAMERA_PARAM_SUPPORTED_ZOOMRATIOS, mZoomRatios);
if (NS_FAILED(rv)) {
// zoom is not supported
mZoomRatios.Clear();
}
for (uint32_t i = 1; i < mZoomRatios.Length(); ++i) {
// Make sure the camera gave us a properly sorted zoom ratio list!
if (mZoomRatios[i] < mZoomRatios[i - 1]) {
NS_WARNING("Zoom ratios list is out of order, discarding");
DOM_CAMERA_LOGE("zoom[%d]=%fx < zoom[%d]=%fx is out of order\n",
i, mZoomRatios[i] / 100.0, i - 1, mZoomRatios[i - 1] / 100.0);
mZoomRatios.Clear();
break;
}
}
if (mZoomRatios.Length() == 0) {
// Always report that we support at least 1.0x zoom.
*mZoomRatios.AppendElement() = 100;
}
// The return code from GetListAsArray() doesn't matter. If it fails,
// the isoModes array will be empty, and the subsequent loop won't
@ -516,20 +531,15 @@ GonkCameraParameters::SetTranslated(uint32_t aKey, const double& aValue)
case CAMERA_PARAM_ZOOM:
{
if (mZoomRatios.Length() == 0) {
DOM_CAMERA_LOGE("Zoom not supported, can't set %fx\n", aValue);
return NS_ERROR_NOT_AVAILABLE;
}
/**
* Convert from a real zoom multipler (e.g. 2.5x) to
* the index of the nearest supported value.
*/
value = aValue * 100.0;
if (value < mZoomRatios[0]) {
if (value <= mZoomRatios[0]) {
index = 0;
} else if (value > mZoomRatios.LastElement()) {
} else if (value >= mZoomRatios.LastElement()) {
index = mZoomRatios.Length() - 1;
} else {
// mZoomRatios is sorted, so we can binary search it
@ -574,12 +584,13 @@ GonkCameraParameters::GetTranslated(uint32_t aKey, double& aValue)
switch (aKey) {
case CAMERA_PARAM_ZOOM:
rv = GetImpl(CAMERA_PARAM_ZOOM, index);
if (NS_SUCCEEDED(rv)) {
rv = GetImpl(aKey, index);
if (NS_SUCCEEDED(rv) && index >= 0) {
val = mZoomRatios[index] / 100.0;
} else {
// return 1x when zooming is not supported
val = 1.0;
rv = NS_OK;
}
break;

View File

@ -154,29 +154,14 @@ var Camera = {
ok(camcap.isoModes.length == 0, "ISO modes length = " + camcap.isoModes.length);
// The emulator doesn't support zoom, so these parameters will be very constrained
// For more ambitious tests, see test_camera_fake_parameters.html
ok(Camera._zoomRatios.length == 1, "zoom ratios length = " + Camera._zoomRatios.length);
if (Camera._zoomRatios.length > 0) {
Camera._zoomRatios.forEach(function(element, index) {
info("zoom[" + index + "] = " + element + "x");
Camera.setZoom(element);
ok(Camera.getZoom() === element, "zoom[" + index + "] = " + element + "x");
});
var zoom = Camera._zoomRatios[0] - 0.1;
Camera.setZoom(zoom);
ok(Camera.getZoom() === Camera._zoomRatios[0],
zoom + "x zoom clamps to minimum: " + Camera._zoomRatios[0]);
zoom = Camera._zoomRatios.slice(-1)[0] + 1.0;
Camera.setZoom(zoom);
ok(Camera.getZoom() === Camera._zoomRatios[0],
zoom + "x zoom clamps to maximum: " + Camera._zoomRatios.slice(-1)[0]);
if (Camera._zoomRatios.length > 1) {
zoom = (Camera._zoomRatios[0] + Camera._zoomRatios[1]) / 2;
Camera.setZoom(zoom);
ok(Camera.getZoom() === Camera._zoomRatios[0],
zoom + "x zoom rounded down to maximum: " + Camera._zoomRatios.slice[0]);
}
}
ok(Camera.cameraObj.zoom == 1.0, "zoom = " + Camera.cameraObj.zoom);
// Test snapping to supported values
Camera.cameraObj.zoom = 0.9;
ok(Camera.cameraObj.zoom == 1.0, "zoom = " + Camera.cameraObj.zoom);
Camera.cameraObj.zoom = 1.1;
ok(Camera.cameraObj.zoom == 1.0, "zoom = " + Camera.cameraObj.zoom);
Camera._tests = new Array();
for (var i in Camera._pictureSizes) {

View File

@ -51,7 +51,10 @@ function run() {
CameraTest.run();
}
// The array of tests
// The array of tests. Because camera capabilities don't change over the life
// of a CameraControl object, they are only read once when the CameraControl is
// created; so we have to call the 'prep' function first to set the fake
// capability pref, before we call getCamera() and call 'test' to run the test.
var tests = [
{
key: "fake-zoom",
@ -96,6 +99,21 @@ var tests = [
next();
}
},
{
key: "fake-zoom-out-of-order",
prep: function setupFakeZoomOutOfOrder(test) {
// We expect the camera library to give us zoom ratios in order; if
// it doesn't we ignore the list and just return 1x support.
test.setFakeParameters("zoom-ratios=100,150,200,400,300;max-zoom=4", function () {
run();
});
},
test: function testFakeZoomOutOfOrder(cam, cap) {
ok(cap.zoomRatios.length == 1, "zoom ratios length = " + cap.zoomRatios.length);
ok(cap.zoomRatios[0] == 1.0, "only supported zoom = " + cap.zoomRatios[0] + "x");
next();
}
},
{
key: "fake-iso",
prep: function setupFakeIso(test) {
@ -108,7 +126,7 @@ var tests = [
});
},
test: function testFakeIso(cam, cap) {
// value 'foo' should be missing
// values 'foo' and 'ISObar' should not be included in isoModes
ok(cap.isoModes.length == 7, "ISO modes length = " + cap.isoModes.length);
ok(cap.isoModes.indexOf("foo") == -1, "Unknown ISO mode 'foo' is ignored");
ok(cap.isoModes.indexOf("ISObar") == -1, "Unknown ISO mode 'ISObar' is ignored");
@ -152,7 +170,15 @@ CameraTest.begin("hardware", function(test) {
info("test: " + t.key);
function onSuccess(camera, config) {
cameraObj = camera;
t.test(camera, camera.capabilities);
document.getElementById('viewfinder').mozSrcObject = camera;
camera.onPreviewStateChange = function (state) {
if (state === "started") {
t.test(camera, camera.capabilities);
} else {
ok(false, "preview started (state = '" + state + "')");
}
camera.onPreviewStateChange = null;
};
}
CameraTest.run = function() {
navigator.mozCameras.getCamera(whichCamera, initialConfig, onSuccess, onError);