use of android.util.Size in project android_frameworks_base by ResurrectionRemix.
the class CameraTestUtils method verifyJpegKeys.
/**
* Verify the JPEG EXIF and JPEG related keys in a capture result are expected.
* - Capture request get values are same as were set.
* - capture result's exif data is the same as was set by
* the capture request.
* - new tags in the result set by the camera service are
* present and semantically correct.
*
* @param image The output JPEG image to verify.
* @param captureResult The capture result to verify.
* @param expectedSize The expected JPEG size.
* @param expectedThumbnailSize The expected thumbnail size.
* @param expectedExifData The expected EXIF data
* @param staticInfo The static metadata for the camera device.
* @param jpegFilename The filename to dump the jpeg to.
* @param collector The camera error collector to collect errors.
*/
public static void verifyJpegKeys(Image image, CaptureResult captureResult, Size expectedSize, Size expectedThumbnailSize, ExifTestData expectedExifData, StaticMetadata staticInfo, CameraErrorCollector collector) throws Exception {
basicValidateJpegImage(image, expectedSize);
byte[] jpegBuffer = getDataFromImage(image);
// Have to dump into a file to be able to use ExifInterface
String jpegFilename = DEBUG_FILE_NAME_BASE + "/verifyJpegKeys.jpeg";
dumpFile(jpegFilename, jpegBuffer);
ExifInterface exif = new ExifInterface(jpegFilename);
if (expectedThumbnailSize.equals(new Size(0, 0))) {
collector.expectTrue("Jpeg shouldn't have thumbnail when thumbnail size is (0, 0)", !exif.hasThumbnail());
} else {
collector.expectTrue("Jpeg must have thumbnail for thumbnail size " + expectedThumbnailSize, exif.hasThumbnail());
}
// Validate capture result vs. request
Size resultThumbnailSize = captureResult.get(CaptureResult.JPEG_THUMBNAIL_SIZE);
int orientationTested = expectedExifData.jpegOrientation;
// Legacy shim always doesn't rotate thumbnail size
if ((orientationTested == 90 || orientationTested == 270) && staticInfo.isHardwareLevelLimitedOrBetter()) {
int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, /*defaultValue*/
-1);
if (exifOrientation == ExifInterface.ORIENTATION_UNDEFINED) {
// Device physically rotated image+thumbnail data
// Expect thumbnail size to be also rotated
resultThumbnailSize = new Size(resultThumbnailSize.getHeight(), resultThumbnailSize.getWidth());
}
}
collector.expectEquals("JPEG thumbnail size result and request should match", expectedThumbnailSize, resultThumbnailSize);
if (collector.expectKeyValueNotNull(captureResult, CaptureResult.JPEG_GPS_LOCATION) != null) {
collector.expectTrue("GPS location result and request should match.", areGpsFieldsEqual(expectedExifData.gpsLocation, captureResult.get(CaptureResult.JPEG_GPS_LOCATION)));
}
collector.expectEquals("JPEG orientation result and request should match", expectedExifData.jpegOrientation, captureResult.get(CaptureResult.JPEG_ORIENTATION));
collector.expectEquals("JPEG quality result and request should match", expectedExifData.jpegQuality, captureResult.get(CaptureResult.JPEG_QUALITY));
collector.expectEquals("JPEG thumbnail quality result and request should match", expectedExifData.thumbnailQuality, captureResult.get(CaptureResult.JPEG_THUMBNAIL_QUALITY));
// Validate other exif tags for all non-legacy devices
if (!staticInfo.isHardwareLevelLegacy()) {
verifyJpegExifExtraTags(exif, expectedSize, captureResult, staticInfo, collector);
}
}
use of android.util.Size in project android_frameworks_base by ResurrectionRemix.
the class CameraTestUtils method verifyJpegExifExtraTags.
/**
* Verify extra tags in JPEG EXIF
*/
private static void verifyJpegExifExtraTags(ExifInterface exif, Size jpegSize, CaptureResult result, StaticMetadata staticInfo, CameraErrorCollector collector) throws ParseException {
/**
* TAG_IMAGE_WIDTH and TAG_IMAGE_LENGTH and TAG_ORIENTATION.
* Orientation and exif width/height need to be tested carefully, two cases:
*
* 1. Device rotate the image buffer physically, then exif width/height may not match
* the requested still capture size, we need swap them to check.
*
* 2. Device use the exif tag to record the image orientation, it doesn't rotate
* the jpeg image buffer itself. In this case, the exif width/height should always match
* the requested still capture size, and the exif orientation should always match the
* requested orientation.
*
*/
int exifWidth = exif.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, /*defaultValue*/
0);
int exifHeight = exif.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, /*defaultValue*/
0);
Size exifSize = new Size(exifWidth, exifHeight);
// Orientation could be missing, which is ok, default to 0.
int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, /*defaultValue*/
-1);
// Get requested orientation from result, because they should be same.
if (collector.expectKeyValueNotNull(result, CaptureResult.JPEG_ORIENTATION) != null) {
int requestedOrientation = result.get(CaptureResult.JPEG_ORIENTATION);
final int ORIENTATION_MIN = ExifInterface.ORIENTATION_UNDEFINED;
final int ORIENTATION_MAX = ExifInterface.ORIENTATION_ROTATE_270;
boolean orientationValid = collector.expectTrue(String.format("Exif orientation must be in range of [%d, %d]", ORIENTATION_MIN, ORIENTATION_MAX), exifOrientation >= ORIENTATION_MIN && exifOrientation <= ORIENTATION_MAX);
if (orientationValid) {
/**
* Device captured image doesn't respect the requested orientation,
* which means it rotates the image buffer physically. Then we
* should swap the exif width/height accordingly to compare.
*/
boolean deviceRotatedImage = exifOrientation == ExifInterface.ORIENTATION_UNDEFINED;
if (deviceRotatedImage) {
// Case 1.
boolean needSwap = (requestedOrientation % 180 == 90);
if (needSwap) {
exifSize = new Size(exifHeight, exifWidth);
}
} else {
// Case 2.
collector.expectEquals("Exif orientaiton should match requested orientation", requestedOrientation, getExifOrientationInDegree(exifOrientation, collector));
}
}
}
/**
* Ideally, need check exifSize == jpegSize == actual buffer size. But
* jpegSize == jpeg decode bounds size(from jpeg jpeg frame
* header, not exif) was validated in ImageReaderTest, no need to
* validate again here.
*/
collector.expectEquals("Exif size should match jpeg capture size", jpegSize, exifSize);
// TAG_DATETIME, it should be local time
long currentTimeInMs = System.currentTimeMillis();
long currentTimeInSecond = currentTimeInMs / 1000;
Date date = new Date(currentTimeInMs);
String localDatetime = new SimpleDateFormat("yyyy:MM:dd HH:").format(date);
String dateTime = exif.getAttribute(ExifInterface.TAG_DATETIME);
if (collector.expectTrue("Exif TAG_DATETIME shouldn't be null", dateTime != null)) {
collector.expectTrue("Exif TAG_DATETIME is wrong", dateTime.length() == EXIF_DATETIME_LENGTH);
long exifTimeInSecond = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss").parse(dateTime).getTime() / 1000;
long delta = currentTimeInSecond - exifTimeInSecond;
collector.expectTrue("Capture time deviates too much from the current time", Math.abs(delta) < EXIF_DATETIME_ERROR_MARGIN_SEC);
// It should be local time.
collector.expectTrue("Exif date time should be local time", dateTime.startsWith(localDatetime));
}
// TAG_FOCAL_LENGTH.
float[] focalLengths = staticInfo.getAvailableFocalLengthsChecked();
float exifFocalLength = (float) exif.getAttributeDouble(ExifInterface.TAG_FOCAL_LENGTH, -1);
collector.expectEquals("Focal length should match", getClosestValueInArray(focalLengths, exifFocalLength), exifFocalLength, EXIF_FOCAL_LENGTH_ERROR_MARGIN);
// More checks for focal length.
collector.expectEquals("Exif focal length should match capture result", validateFocalLength(result, staticInfo, collector), exifFocalLength);
// TAG_EXPOSURE_TIME
// ExifInterface API gives exposure time value in the form of float instead of rational
String exposureTime = exif.getAttribute(ExifInterface.TAG_EXPOSURE_TIME);
collector.expectNotNull("Exif TAG_EXPOSURE_TIME shouldn't be null", exposureTime);
if (staticInfo.areKeysAvailable(CaptureResult.SENSOR_EXPOSURE_TIME)) {
if (exposureTime != null) {
double exposureTimeValue = Double.parseDouble(exposureTime);
long expTimeResult = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
double expected = expTimeResult / 1e9;
double tolerance = expected * EXIF_EXPOSURE_TIME_ERROR_MARGIN_RATIO;
tolerance = Math.max(tolerance, EXIF_EXPOSURE_TIME_MIN_ERROR_MARGIN_SEC);
collector.expectEquals("Exif exposure time doesn't match", expected, exposureTimeValue, tolerance);
}
}
// TAG_APERTURE
// ExifInterface API gives aperture value in the form of float instead of rational
String exifAperture = exif.getAttribute(ExifInterface.TAG_APERTURE);
collector.expectNotNull("Exif TAG_APERTURE shouldn't be null", exifAperture);
if (staticInfo.areKeysAvailable(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES)) {
float[] apertures = staticInfo.getAvailableAperturesChecked();
if (exifAperture != null) {
float apertureValue = Float.parseFloat(exifAperture);
collector.expectEquals("Aperture value should match", getClosestValueInArray(apertures, apertureValue), apertureValue, EXIF_APERTURE_ERROR_MARGIN);
// More checks for aperture.
collector.expectEquals("Exif aperture length should match capture result", validateAperture(result, staticInfo, collector), apertureValue);
}
}
/**
* TAG_FLASH. TODO: For full devices, can check a lot more info
* (http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html#Flash)
*/
String flash = exif.getAttribute(ExifInterface.TAG_FLASH);
collector.expectNotNull("Exif TAG_FLASH shouldn't be null", flash);
/**
* TAG_WHITE_BALANCE. TODO: For full devices, with the DNG tags, we
* should be able to cross-check android.sensor.referenceIlluminant.
*/
String whiteBalance = exif.getAttribute(ExifInterface.TAG_WHITE_BALANCE);
collector.expectNotNull("Exif TAG_WHITE_BALANCE shouldn't be null", whiteBalance);
// TAG_MAKE
String make = exif.getAttribute(ExifInterface.TAG_MAKE);
collector.expectEquals("Exif TAG_MAKE is incorrect", Build.MANUFACTURER, make);
// TAG_MODEL
String model = exif.getAttribute(ExifInterface.TAG_MODEL);
collector.expectEquals("Exif TAG_MODEL is incorrect", Build.MODEL, model);
// TAG_ISO
int iso = exif.getAttributeInt(ExifInterface.TAG_ISO, /*defaultValue*/
-1);
if (staticInfo.areKeysAvailable(CaptureResult.SENSOR_SENSITIVITY)) {
int expectedIso = result.get(CaptureResult.SENSOR_SENSITIVITY);
collector.expectEquals("Exif TAG_ISO is incorrect", expectedIso, iso);
}
// TAG_DATETIME_DIGITIZED (a.k.a Create time for digital cameras).
String digitizedTime = exif.getAttribute(ExifInterface.TAG_DATETIME_DIGITIZED);
collector.expectNotNull("Exif TAG_DATETIME_DIGITIZED shouldn't be null", digitizedTime);
if (digitizedTime != null) {
String expectedDateTime = exif.getAttribute(ExifInterface.TAG_DATETIME);
collector.expectNotNull("Exif TAG_DATETIME shouldn't be null", expectedDateTime);
if (expectedDateTime != null) {
collector.expectEquals("dataTime should match digitizedTime", expectedDateTime, digitizedTime);
}
}
/**
* TAG_SUBSEC_TIME. Since the sub second tag strings are truncated to at
* most 9 digits in ExifInterface implementation, use getAttributeInt to
* sanitize it. When the default value -1 is returned, it means that
* this exif tag either doesn't exist or is a non-numerical invalid
* string. Same rule applies to the rest of sub second tags.
*/
int subSecTime = exif.getAttributeInt(ExifInterface.TAG_SUBSEC_TIME, /*defaultValue*/
-1);
collector.expectTrue("Exif TAG_SUBSEC_TIME value is null or invalid!", subSecTime > 0);
// TAG_SUBSEC_TIME_ORIG
int subSecTimeOrig = exif.getAttributeInt(ExifInterface.TAG_SUBSEC_TIME_ORIG, /*defaultValue*/
-1);
collector.expectTrue("Exif TAG_SUBSEC_TIME_ORIG value is null or invalid!", subSecTimeOrig > 0);
// TAG_SUBSEC_TIME_DIG
int subSecTimeDig = exif.getAttributeInt(ExifInterface.TAG_SUBSEC_TIME_DIG, /*defaultValue*/
-1);
collector.expectTrue("Exif TAG_SUBSEC_TIME_DIG value is null or invalid!", subSecTimeDig > 0);
}
use of android.util.Size in project android_frameworks_base by ResurrectionRemix.
the class CameraTestUtils method getSupportedVideoSizes.
/**
* Get supported video size list for a given camera device.
*
* <p>
* Filter out the sizes that are larger than the bound. If the bound is
* null, don't do the size bound filtering.
* </p>
*/
public static List<Size> getSupportedVideoSizes(String cameraId, CameraManager cameraManager, Size bound) throws CameraAccessException {
Size[] rawSizes = getSupportedSizeForClass(android.media.MediaRecorder.class, cameraId, cameraManager);
assertArrayNotEmpty(rawSizes, "Available sizes for MediaRecorder class should not be empty");
if (VERBOSE) {
Log.v(TAG, "Supported sizes are: " + Arrays.deepToString(rawSizes));
}
if (bound == null) {
return getAscendingOrderSizes(Arrays.asList(rawSizes), /*ascending*/
false);
}
List<Size> sizes = new ArrayList<Size>();
for (Size sz : rawSizes) {
if (sz.getWidth() <= bound.getWidth() && sz.getHeight() <= bound.getHeight()) {
sizes.add(sz);
}
}
return getAscendingOrderSizes(sizes, /*ascending*/
false);
}
use of android.util.Size in project android_frameworks_base by ResurrectionRemix.
the class StaticMetadata method getRawDimensChecked.
/**
* Get the dimensions to use for RAW16 buffers.
*/
public Size getRawDimensChecked() throws Exception {
Size[] targetCaptureSizes = getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR, StaticMetadata.StreamDirection.Output);
Assert.assertTrue("No capture sizes available for RAW format!", targetCaptureSizes.length != 0);
Rect activeArray = getPreCorrectedActiveArraySizeChecked();
Size preCorrectionActiveArraySize = new Size(activeArray.width(), activeArray.height());
Size pixelArraySize = getPixelArraySizeChecked();
Assert.assertTrue("Missing pre-correction active array size", activeArray.width() > 0 && activeArray.height() > 0);
Assert.assertTrue("Missing pixel array size", pixelArraySize.getWidth() > 0 && pixelArraySize.getHeight() > 0);
Size[] allowedArraySizes = new Size[] { preCorrectionActiveArraySize, pixelArraySize };
return assertArrayContainsAnyOf("Available sizes for RAW format" + " must include either the pre-corrected active array size, or the full " + "pixel array size", targetCaptureSizes, allowedArraySizes);
}
use of android.util.Size in project android_frameworks_base by ResurrectionRemix.
the class StaticMetadata method isHighSpeedVideoSupported.
/**
* Check if high speed video is supported (HIGH_SPEED_VIDEO scene mode is
* supported, supported high speed fps ranges and sizes are valid).
*
* @return true if high speed video is supported.
*/
public boolean isHighSpeedVideoSupported() {
List<Integer> sceneModes = Arrays.asList(CameraTestUtils.toObject(getAvailableSceneModesChecked()));
if (sceneModes.contains(CameraCharacteristics.CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO)) {
StreamConfigurationMap config = getValueFromKeyNonNull(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (config == null) {
return false;
}
Size[] availableSizes = config.getHighSpeedVideoSizes();
if (availableSizes.length == 0) {
return false;
}
for (Size size : availableSizes) {
Range<Integer>[] availableFpsRanges = config.getHighSpeedVideoFpsRangesFor(size);
if (availableFpsRanges.length == 0) {
return false;
}
}
return true;
} else {
return false;
}
}
Aggregations