mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 976802 - add support for testing fake CameraParameters, r=dhylands
This commit is contained in:
parent
6908b035ed
commit
7e59fa5afc
@ -147,15 +147,18 @@ GonkCameraParameters::Initialize()
|
|||||||
|
|
||||||
rv = GetImpl(CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION, mExposureCompensationMin);
|
rv = GetImpl(CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION, mExposureCompensationMin);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
NS_WARNING("Failed to initialize minimum exposure compensation");
|
||||||
|
mExposureCompensationMin = 0;
|
||||||
}
|
}
|
||||||
rv = GetImpl(CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP, mExposureCompensationStep);
|
rv = GetImpl(CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP, mExposureCompensationStep);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
NS_WARNING("Failed to initialize exposure compensation step size");
|
||||||
|
mExposureCompensationStep = 0;
|
||||||
}
|
}
|
||||||
rv = GetListAsArray(CAMERA_PARAM_SUPPORTED_ZOOMRATIOS, mZoomRatios);
|
rv = GetListAsArray(CAMERA_PARAM_SUPPORTED_ZOOMRATIOS, mZoomRatios);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
// zoom is not supported
|
||||||
|
mZoomRatios.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
mInitialized = true;
|
mInitialized = true;
|
||||||
@ -410,6 +413,11 @@ GonkCameraParameters::SetTranslated(uint32_t aKey, const double& aValue)
|
|||||||
|
|
||||||
switch (aKey) {
|
switch (aKey) {
|
||||||
case CAMERA_PARAM_EXPOSURECOMPENSATION:
|
case CAMERA_PARAM_EXPOSURECOMPENSATION:
|
||||||
|
if (mExposureCompensationStep == 0) {
|
||||||
|
DOM_CAMERA_LOGE("Exposure compensation not supported, can't set %f\n", aValue);
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert from real value to a Gonk index, round
|
* Convert from real value to a Gonk index, round
|
||||||
* to the nearest step; index is 1-based.
|
* to the nearest step; index is 1-based.
|
||||||
@ -422,34 +430,46 @@ GonkCameraParameters::SetTranslated(uint32_t aKey, const double& aValue)
|
|||||||
|
|
||||||
case CAMERA_PARAM_ZOOM:
|
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
|
* Convert from a real zoom multipler (e.g. 2.5x) to
|
||||||
* the index of the nearest supported value.
|
* the index of the nearest supported value.
|
||||||
*/
|
*/
|
||||||
value = aValue * 100.0;
|
value = aValue * 100.0;
|
||||||
|
|
||||||
// mZoomRatios is sorted, so we can binary search it
|
if (value < mZoomRatios[0]) {
|
||||||
unsigned int bottom = 0;
|
index = 0;
|
||||||
unsigned int top = mZoomRatios.Length() - 1;
|
} else if (value > mZoomRatios.LastElement()) {
|
||||||
unsigned int middle;
|
index = mZoomRatios.Length() - 1;
|
||||||
|
} else {
|
||||||
|
// mZoomRatios is sorted, so we can binary search it
|
||||||
|
int bottom = 0;
|
||||||
|
int top = mZoomRatios.Length() - 1;
|
||||||
|
int middle;
|
||||||
|
|
||||||
while (bottom != top) {
|
while (top >= bottom) {
|
||||||
middle = (top + bottom) / 2;
|
middle = (top + bottom) / 2;
|
||||||
if (value == mZoomRatios[middle]) {
|
if (value == mZoomRatios[middle]) {
|
||||||
// exact match
|
// exact match
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (value > mZoomRatios[middle] && value < mZoomRatios[middle + 1]) {
|
if (value > mZoomRatios[middle] && value < mZoomRatios[middle + 1]) {
|
||||||
// the specified zoom value lies in this interval
|
// the specified zoom value lies in this interval
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (value > mZoomRatios[middle]) {
|
if (value > mZoomRatios[middle]) {
|
||||||
bottom = middle + 1;
|
bottom = middle + 1;
|
||||||
} else {
|
} else {
|
||||||
top = middle - 1;
|
top = middle - 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
index = middle;
|
||||||
}
|
}
|
||||||
index = middle;
|
DOM_CAMERA_LOGI("Zoom = %fx --> index = %d\n", aValue, index);
|
||||||
}
|
}
|
||||||
return SetImpl(CAMERA_PARAM_ZOOM, index);
|
return SetImpl(CAMERA_PARAM_ZOOM, index);
|
||||||
}
|
}
|
||||||
@ -616,16 +636,19 @@ GonkCameraParameters::GetListAsArray(uint32_t aKey, nsTArray<T>& aArray)
|
|||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
if (!p) {
|
|
||||||
DOM_CAMERA_LOGW("Camera parameter %d not available (value is null)\n", aKey);
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
if (*p == '\0') {
|
|
||||||
DOM_CAMERA_LOGW("Camera parameter %d not available (value is empty string)\n", aKey);
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
aArray.Clear();
|
aArray.Clear();
|
||||||
|
|
||||||
|
// If there is no value available, just return the empty array.
|
||||||
|
if (!p) {
|
||||||
|
DOM_CAMERA_LOGI("Camera parameter %d not available (value is null)\n", aKey);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
if (*p == '\0') {
|
||||||
|
DOM_CAMERA_LOGI("Camera parameter %d not available (value is empty string)\n", aKey);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
const char* comma;
|
const char* comma;
|
||||||
|
|
||||||
while (p) {
|
while (p) {
|
||||||
|
@ -56,6 +56,33 @@ TestGonkCameraHardware::TestCase()
|
|||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nsCString
|
||||||
|
TestGonkCameraHardware::GetExtraParameters()
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The contents of this pref are appended to the flattened string of
|
||||||
|
* parameters stuffed into GonkCameraParameters by the camera library.
|
||||||
|
* It consists of semicolon-delimited key=value pairs, e.g.
|
||||||
|
*
|
||||||
|
* focus-mode=auto;flash-mode=auto;preview-size=1024x768
|
||||||
|
*
|
||||||
|
* The unflattening process breaks this string up on semicolon boundaries
|
||||||
|
* and sets an entry in a hashtable of strings with the token before
|
||||||
|
* the equals sign as the key, and the token after as the value. Because
|
||||||
|
* the string is parsed in order, key=value pairs occuring later in the
|
||||||
|
* string will replace value pairs appearing earlier, making it easy to
|
||||||
|
* inject fake, testable values into the parameters table.
|
||||||
|
*
|
||||||
|
* One constraint of this approach is that neither the key nor the value
|
||||||
|
* may contain equals signs or semicolons. We don't enforce that here
|
||||||
|
* so that we can also test correct handling of improperly-formatted values.
|
||||||
|
*/
|
||||||
|
const nsCString parameters = Preferences::GetCString("camera.control.test.hardware.gonk.parameters");
|
||||||
|
DOM_CAMERA_LOGA("TestGonkCameraHardware : extra-parameters '%s'\n",
|
||||||
|
parameters.get());
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TestGonkCameraHardware::IsTestCaseInternal(const char* aTest, const char* aFile, int aLine)
|
TestGonkCameraHardware::IsTestCaseInternal(const char* aTest, const char* aFile, int aLine)
|
||||||
{
|
{
|
||||||
@ -174,7 +201,14 @@ TestGonkCameraHardware::PullParameters(GonkCameraParameters& aParams)
|
|||||||
return static_cast<nsresult>(TestCaseError(UNKNOWN_ERROR));
|
return static_cast<nsresult>(TestCaseError(UNKNOWN_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
return GonkCameraHardware::PullParameters(aParams);
|
String8 s = mCamera->getParameters();
|
||||||
|
nsCString extra = GetExtraParameters();
|
||||||
|
if (!extra.IsEmpty()) {
|
||||||
|
s += ";";
|
||||||
|
s += extra.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return aParams.Unflatten(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -55,6 +55,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
const nsCString TestCase();
|
const nsCString TestCase();
|
||||||
|
const nsCString GetExtraParameters();
|
||||||
bool IsTestCaseInternal(const char* aTest, const char* aFile, int aLine);
|
bool IsTestCaseInternal(const char* aTest, const char* aFile, int aLine);
|
||||||
int TestCaseError(int aDefaultError);
|
int TestCaseError(int aDefaultError);
|
||||||
|
|
||||||
|
@ -18,13 +18,41 @@ var CameraTest = (function() {
|
|||||||
* 'take-picture-process-failure' will simulate a failure of the
|
* 'take-picture-process-failure' will simulate a failure of the
|
||||||
* asynchronous picture-taking process, even if the initial API call
|
* asynchronous picture-taking process, even if the initial API call
|
||||||
* path seems to have succeeded.
|
* path seems to have succeeded.
|
||||||
|
*
|
||||||
|
* If 'camera.control.test.hardware.gonk.parameters' is set, it will cause
|
||||||
|
* the contents of that string to be appended to the string of parameters
|
||||||
|
* pulled from the Gonk camera library. This allows tests to inject fake
|
||||||
|
* settings/capabilities for features not supported by the emulator. These
|
||||||
|
* parameters are one or more semicolon-delimited key=value pairs, e.g. to
|
||||||
|
* pretend the emulator supports zoom:
|
||||||
|
*
|
||||||
|
* zoom-ratios=100,150,200,300,400;max-zoom=4
|
||||||
|
*
|
||||||
|
* This means (of course) that neither the key not the value tokens can
|
||||||
|
* contain either equals signs or semicolons. The test shim doesn't enforce
|
||||||
|
* this so that we can test getting junk from the camera library as well.
|
||||||
*/
|
*/
|
||||||
const PREF_TEST_ENABLED = "camera.control.test.enabled";
|
const PREF_TEST_ENABLED = "camera.control.test.enabled";
|
||||||
const PREF_TEST_HARDWARE = "camera.control.test.hardware";
|
const PREF_TEST_HARDWARE = "camera.control.test.hardware";
|
||||||
|
const PREF_TEST_EXTRA_PARAMETERS = "camera.control.test.hardware.gonk.parameters";
|
||||||
var oldTestEnabled;
|
var oldTestEnabled;
|
||||||
var oldTestHw;
|
var oldTestHw;
|
||||||
var testMode;
|
var testMode;
|
||||||
|
|
||||||
|
function testHardwareSetFakeParameters(parameters, callback) {
|
||||||
|
SpecialPowers.pushPrefEnv({'set': [[PREF_TEST_EXTRA_PARAMETERS, parameters]]}, function() {
|
||||||
|
var setParams = SpecialPowers.getCharPref(PREF_TEST_EXTRA_PARAMETERS);
|
||||||
|
ise(setParams, parameters, "Extra test parameters '" + setParams + "'");
|
||||||
|
if (callback) {
|
||||||
|
callback(setParams);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testHardwareClearFakeParameters(callback) {
|
||||||
|
SpecialPowers.pushPrefEnv({'clear': [[PREF_TEST_EXTRA_PARAMETERS]]}, callback);
|
||||||
|
}
|
||||||
|
|
||||||
function testHardwareSet(test, callback) {
|
function testHardwareSet(test, callback) {
|
||||||
SpecialPowers.pushPrefEnv({'set': [[PREF_TEST_HARDWARE, test]]}, function() {
|
SpecialPowers.pushPrefEnv({'set': [[PREF_TEST_HARDWARE, test]]}, function() {
|
||||||
var setTest = SpecialPowers.getCharPref(PREF_TEST_HARDWARE);
|
var setTest = SpecialPowers.getCharPref(PREF_TEST_HARDWARE);
|
||||||
@ -58,6 +86,8 @@ var CameraTest = (function() {
|
|||||||
} catch(e) { }
|
} catch(e) { }
|
||||||
testMode = {
|
testMode = {
|
||||||
set: testHardwareSet,
|
set: testHardwareSet,
|
||||||
|
setFakeParameters: testHardwareSetFakeParameters,
|
||||||
|
clearFakeParameters: testHardwareClearFakeParameters,
|
||||||
done: testHardwareDone
|
done: testHardwareDone
|
||||||
};
|
};
|
||||||
if (callback) {
|
if (callback) {
|
||||||
@ -68,32 +98,40 @@ var CameraTest = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function testEnd(callback) {
|
function testEnd(callback) {
|
||||||
function allDone(cb) {
|
// A chain of clean-up functions....
|
||||||
function cb2() {
|
function allCleanedUp() {
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
if (cb) {
|
if (callback) {
|
||||||
cb();
|
callback();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
function cleanUpTestEnabled() {
|
||||||
|
var next = allCleanedUp;
|
||||||
if (oldTestEnabled) {
|
if (oldTestEnabled) {
|
||||||
SpecialPowers.pushPrefEnv({'set': [[PREF_TEST_ENABLED, oldTestEnabled]]}, cb2);
|
SpecialPowers.pushPrefEnv({'set': [[PREF_TEST_ENABLED, oldTestEnabled]]}, next);
|
||||||
} else {
|
} else {
|
||||||
SpecialPowers.pushPrefEnv({'clear': [[PREF_TEST_ENABLED]]}, cb2);
|
SpecialPowers.pushPrefEnv({'clear': [[PREF_TEST_ENABLED]]}, next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function cleanUpTest() {
|
||||||
|
var next = cleanUpTestEnabled;
|
||||||
|
if (testMode) {
|
||||||
|
testMode.done(next);
|
||||||
|
testMode = null;
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function cleanUpExtraParameters() {
|
||||||
|
var next = cleanUpTest;
|
||||||
|
if (testMode) {
|
||||||
|
testMode.clearFakeParameters(next);
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (testMode) {
|
cleanUpExtraParameters();
|
||||||
testMode.done(function() {
|
|
||||||
allDone(callback);
|
|
||||||
});
|
|
||||||
testMode = null;
|
|
||||||
} else {
|
|
||||||
allDone(function() {
|
|
||||||
if (callback) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ise(SpecialPowers.sanityCheck(), "foo", "SpecialPowers passed sanity check");
|
ise(SpecialPowers.sanityCheck(), "foo", "SpecialPowers passed sanity check");
|
||||||
|
@ -7,3 +7,4 @@ support-files = camera_common.js
|
|||||||
[test_camera_hardware_init_failure.html]
|
[test_camera_hardware_init_failure.html]
|
||||||
[test_camera_hardware_failures.html]
|
[test_camera_hardware_failures.html]
|
||||||
[test_bug975472.html]
|
[test_bug975472.html]
|
||||||
|
[test_camera_fake_parameters.html]
|
||||||
|
135
dom/camera/test/test_camera_fake_parameters.html
Normal file
135
dom/camera/test/test_camera_fake_parameters.html
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test for CameraParameters we need to fake</title>
|
||||||
|
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="text/javascript" src="camera_common.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=976802">Mozilla Bug 976802</a>
|
||||||
|
<video id="viewfinder" width="200" height="200" autoplay></video>
|
||||||
|
<img src="#" alt="This image is going to load" id="testimage"/>
|
||||||
|
|
||||||
|
<script class="testbody" type="text/javascript;version=1.7">
|
||||||
|
|
||||||
|
var whichCamera = navigator.mozCameras.getListOfCameras()[0];
|
||||||
|
var initialConfig = {
|
||||||
|
mode: 'picture',
|
||||||
|
recorderProfile: 'cif',
|
||||||
|
previewSize: {
|
||||||
|
width: 352,
|
||||||
|
height: 288
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var cameraObj = null;
|
||||||
|
|
||||||
|
// Shorthand functions
|
||||||
|
function end() {
|
||||||
|
CameraTest.end();
|
||||||
|
}
|
||||||
|
function next() {
|
||||||
|
CameraTest.next();
|
||||||
|
}
|
||||||
|
function run() {
|
||||||
|
CameraTest.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onError(e) {
|
||||||
|
ok(false, "Error" + JSON.stringify(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The array of tests
|
||||||
|
var tests = [
|
||||||
|
{
|
||||||
|
key: "fake-zoom",
|
||||||
|
prep: function setupFakeZoom(test) {
|
||||||
|
test.setFakeParameters("zoom-ratios=100,150,200,300,400;max-zoom=4", function() {
|
||||||
|
run();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
test: function testFakeZoom(cam, cap) {
|
||||||
|
ok(cap.zoomRatios.length == 5, "zoom ratios length = " + cap.zoomRatios.length);
|
||||||
|
|
||||||
|
// test individual zoom ratios
|
||||||
|
cap.zoomRatios.forEach(function(zoom, index) {
|
||||||
|
cam.zoom = zoom;
|
||||||
|
ok(cam.zoom === zoom,
|
||||||
|
"zoom[" + index + "] = " + zoom + "x, cam.zoom = " + cam.zoom + "x");
|
||||||
|
});
|
||||||
|
|
||||||
|
// test below-lower-bound zoom ratio
|
||||||
|
var zoom = cap.zoomRatios[0] - 0.1;
|
||||||
|
cam.zoom = zoom;
|
||||||
|
ok(cam.zoom === cap.zoomRatios[0],
|
||||||
|
zoom + "x zoom clamps to minimum: " +
|
||||||
|
cap.zoomRatios[0] + "x, cam.zoom = " + cam.zoom + "x");
|
||||||
|
|
||||||
|
// test above-upper-bound zoom ratio
|
||||||
|
zoom = cap.zoomRatios.slice(-1)[0] + 1.0;
|
||||||
|
cam.zoom = zoom;
|
||||||
|
ok(cam.zoom === cap.zoomRatios.slice(-1)[0],
|
||||||
|
zoom + "x zoom clamps to maximum: " + cap.zoomRatios.slice(-1)[0] +
|
||||||
|
"x, cam.zoom = " + cam.zoom + "x");
|
||||||
|
|
||||||
|
// test snapping to supported zoom ratio
|
||||||
|
if (cap.zoomRatios.length > 1) {
|
||||||
|
zoom = (cap.zoomRatios[0] + cap.zoomRatios[1]) / 2;
|
||||||
|
cam.zoom = zoom;
|
||||||
|
ok(cam.zoom === cap.zoomRatios[0],
|
||||||
|
zoom + "x zoom rounded down to: " + cap.zoomRatios[0] +
|
||||||
|
"x, cam.zoom = " + cam.zoom + "x");
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
var testGenerator = function() {
|
||||||
|
for (var i = 0; i < tests.length; ++i ) {
|
||||||
|
yield tests[i];
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
window.addEventListener('beforeunload', function() {
|
||||||
|
document.getElementById('viewfinder').mozSrcObject = null;
|
||||||
|
cameraObj.release();
|
||||||
|
cameraObj = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
CameraTest.begin("hardware", function(test) {
|
||||||
|
function onError(error) {
|
||||||
|
ok(false, "getCamera() failed with: " + error);
|
||||||
|
end();
|
||||||
|
}
|
||||||
|
|
||||||
|
CameraTest.next = function() {
|
||||||
|
try {
|
||||||
|
var t = testGenerator.next();
|
||||||
|
info("test: " + t.key);
|
||||||
|
function onSuccess(camera, config) {
|
||||||
|
cameraObj = camera;
|
||||||
|
t.test(camera, camera.capabilities);
|
||||||
|
}
|
||||||
|
CameraTest.run = function() {
|
||||||
|
navigator.mozCameras.getCamera(whichCamera, initialConfig, onSuccess, onError);
|
||||||
|
};
|
||||||
|
t.prep(test);
|
||||||
|
} catch(e) {
|
||||||
|
if (e instanceof StopIteration) {
|
||||||
|
end();
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user