use of android.util.Size in project platform_frameworks_base by android.
the class Camera2RecordingTest method videoSnapshotTestByCamera.
/**
* Test video snapshot for each available CamcorderProfile for a given camera.
*
* <p>
* Preview size is set to the video size. For the burst test, frame drop and jittering
* is not checked.
* </p>
*
* @param burstTest Perform burst capture or single capture. For burst capture
* {@value #BURST_VIDEO_SNAPSHOT_NUM} capture requests will be sent.
*/
private void videoSnapshotTestByCamera(boolean burstTest) throws Exception {
final int NUM_SINGLE_SHOT_TEST = 5;
final int FRAMEDROP_TOLERANCE = 8;
final int FRAME_SIZE_15M = 15000000;
final float FRAME_DROP_TOLERENCE_FACTOR = 1.5f;
int kFrameDrop_Tolerence = FRAMEDROP_TOLERANCE;
for (int profileId : mCamcorderProfileList) {
int cameraId = Integer.parseInt(mCamera.getId());
if (!CamcorderProfile.hasProfile(cameraId, profileId) || allowedUnsupported(cameraId, profileId)) {
continue;
}
CamcorderProfile profile = CamcorderProfile.get(cameraId, profileId);
Size videoSz = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
Size maxPreviewSize = mOrderedPreviewSizes.get(0);
if (mStaticInfo.isHardwareLevelLegacy() && (videoSz.getWidth() > maxPreviewSize.getWidth() || videoSz.getHeight() > maxPreviewSize.getHeight())) {
// Skip. Legacy mode can only do recording up to max preview size
continue;
}
if (!mSupportedVideoSizes.contains(videoSz)) {
mCollector.addMessage("Video size " + videoSz.toString() + " for profile ID " + profileId + " must be one of the camera device supported video size!");
continue;
}
// For LEGACY, find closest supported smaller or equal JPEG size to the current video
// size; if no size is smaller than the video, pick the smallest JPEG size. The assert
// for video size above guarantees that for LIMITED or FULL, we select videoSz here.
// Also check for minFrameDuration here to make sure jpeg stream won't slow down
// video capture
Size videoSnapshotSz = mOrderedStillSizes.get(mOrderedStillSizes.size() - 1);
// Allow a bit tolerance so we don't fail for a few nano seconds of difference
final float FRAME_DURATION_TOLERANCE = 0.01f;
long videoFrameDuration = (long) (1e9 / profile.videoFrameRate * (1.0 + FRAME_DURATION_TOLERANCE));
HashMap<Size, Long> minFrameDurationMap = mStaticInfo.getAvailableMinFrameDurationsForFormatChecked(ImageFormat.JPEG);
for (int i = mOrderedStillSizes.size() - 2; i >= 0; i--) {
Size candidateSize = mOrderedStillSizes.get(i);
if (mStaticInfo.isHardwareLevelLegacy()) {
// Legacy level doesn't report min frame duration
if (candidateSize.getWidth() <= videoSz.getWidth() && candidateSize.getHeight() <= videoSz.getHeight()) {
videoSnapshotSz = candidateSize;
}
} else {
Long jpegFrameDuration = minFrameDurationMap.get(candidateSize);
assertTrue("Cannot find minimum frame duration for jpeg size " + candidateSize, jpegFrameDuration != null);
if (candidateSize.getWidth() <= videoSz.getWidth() && candidateSize.getHeight() <= videoSz.getHeight() && jpegFrameDuration <= videoFrameDuration) {
videoSnapshotSz = candidateSize;
}
}
}
/**
* Only test full res snapshot when below conditions are all true.
* 1. Camera is a FULL device
* 2. video size is up to max preview size, which will be bounded by 1080p.
* 3. Full resolution jpeg stream can keep up to video stream speed.
* When full res jpeg stream cannot keep up to video stream speed, search
* the largest jpeg size that can susptain video speed instead.
*/
if (mStaticInfo.isHardwareLevelFull() && videoSz.getWidth() <= maxPreviewSize.getWidth() && videoSz.getHeight() <= maxPreviewSize.getHeight()) {
for (Size jpegSize : mOrderedStillSizes) {
Long jpegFrameDuration = minFrameDurationMap.get(jpegSize);
assertTrue("Cannot find minimum frame duration for jpeg size " + jpegSize, jpegFrameDuration != null);
if (jpegFrameDuration <= videoFrameDuration) {
videoSnapshotSz = jpegSize;
break;
}
if (jpegSize.equals(videoSz)) {
throw new AssertionFailedError("Cannot find adequate video snapshot size for video size" + videoSz);
}
}
}
Log.i(TAG, "Testing video snapshot size " + videoSnapshotSz + " for video size " + videoSz);
if (videoSnapshotSz.getWidth() * videoSnapshotSz.getHeight() > FRAME_SIZE_15M)
kFrameDrop_Tolerence = (int) (FRAMEDROP_TOLERANCE * FRAME_DROP_TOLERENCE_FACTOR);
createImageReader(videoSnapshotSz, ImageFormat.JPEG, MAX_VIDEO_SNAPSHOT_IMAGES, /*listener*/
null);
if (VERBOSE) {
Log.v(TAG, "Testing camera recording with video size " + videoSz.toString());
}
// Configure preview and recording surfaces.
mOutMediaFileName = VIDEO_FILE_PATH + "/test_video.mp4";
if (DEBUG_DUMP) {
mOutMediaFileName = VIDEO_FILE_PATH + "/test_video_" + cameraId + "_" + videoSz.toString() + ".mp4";
}
int numTestIterations = burstTest ? 1 : NUM_SINGLE_SHOT_TEST;
int totalDroppedFrames = 0;
for (int numTested = 0; numTested < numTestIterations; numTested++) {
prepareRecordingWithProfile(profile);
// prepare video snapshot
SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
CaptureRequest.Builder videoSnapshotRequestBuilder = mCamera.createCaptureRequest((mStaticInfo.isHardwareLevelLegacy()) ? CameraDevice.TEMPLATE_RECORD : CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
// prepare preview surface by using video size.
updatePreviewSurfaceWithVideo(videoSz, profile.videoFrameRate);
prepareVideoSnapshot(videoSnapshotRequestBuilder, imageListener);
CaptureRequest request = videoSnapshotRequestBuilder.build();
// Start recording
startRecording(/* useMediaRecorder */
true, resultListener, /*useVideoStab*/
false);
long startTime = SystemClock.elapsedRealtime();
// Record certain duration.
SystemClock.sleep(RECORDING_DURATION_MS / 2);
// take video snapshot
if (burstTest) {
List<CaptureRequest> requests = new ArrayList<CaptureRequest>(BURST_VIDEO_SNAPSHOT_NUM);
for (int i = 0; i < BURST_VIDEO_SNAPSHOT_NUM; i++) {
requests.add(request);
}
mSession.captureBurst(requests, resultListener, mHandler);
} else {
mSession.capture(request, resultListener, mHandler);
}
// make sure recording is still going after video snapshot
SystemClock.sleep(RECORDING_DURATION_MS / 2);
// Stop recording and preview
int durationMs = stopRecording(/* useMediaRecorder */
true);
// of frames to estimate duration
if (!burstTest) {
durationMs = (int) (resultListener.getTotalNumFrames() * 1000.0f / profile.videoFrameRate);
}
// Validation recorded video
validateRecording(videoSz, durationMs);
if (burstTest) {
for (int i = 0; i < BURST_VIDEO_SNAPSHOT_NUM; i++) {
Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
validateVideoSnapshotCapture(image, videoSnapshotSz);
image.close();
}
} else {
// validate video snapshot image
Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
validateVideoSnapshotCapture(image, videoSnapshotSz);
// validate if there is framedrop around video snapshot
totalDroppedFrames += validateFrameDropAroundVideoSnapshot(resultListener, image.getTimestamp());
//TODO: validate jittering. Should move to PTS
//validateJittering(resultListener);
image.close();
}
}
if (!burstTest) {
Log.w(TAG, String.format("Camera %d Video size %s: Number of dropped frames " + "detected in %d trials is %d frames.", cameraId, videoSz.toString(), numTestIterations, totalDroppedFrames));
mCollector.expectLessOrEqual(String.format("Camera %d Video size %s: Number of dropped frames %d must not" + " be larger than %d", cameraId, videoSz.toString(), totalDroppedFrames, kFrameDrop_Tolerence), kFrameDrop_Tolerence, totalDroppedFrames);
}
closeImageReader();
}
}
use of android.util.Size in project platform_frameworks_base by android.
the class CameraTestUtils method getSupportedPreviewSizes.
/**
* Get sorted size list in descending order. Remove the sizes larger than
* the bound. If the bound is null, don't do the size bound filtering.
*/
public static List<Size> getSupportedPreviewSizes(String cameraId, CameraManager cameraManager, Size bound) throws CameraAccessException {
Size[] rawSizes = getSupportedSizeForClass(android.view.SurfaceHolder.class, cameraId, cameraManager);
assertArrayNotEmpty(rawSizes, "Available sizes for SurfaceHolder 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 platform_frameworks_base by android.
the class CameraTestUtils method getSupportedSizeForFormat.
/**
* Get the available output sizes for the user-defined {@code format}.
*
* <p>Note that implementation-defined/hidden formats are not supported.</p>
*/
public static Size[] getSupportedSizeForFormat(int format, String cameraId, CameraManager cameraManager) throws CameraAccessException {
CameraCharacteristics properties = cameraManager.getCameraCharacteristics(cameraId);
assertNotNull("Can't get camera characteristics!", properties);
if (VERBOSE) {
Log.v(TAG, "get camera characteristics for camera: " + cameraId);
}
StreamConfigurationMap configMap = properties.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] availableSizes = configMap.getOutputSizes(format);
assertArrayNotEmpty(availableSizes, "availableSizes should not be empty for format: " + format);
Size[] highResAvailableSizes = configMap.getHighResolutionOutputSizes(format);
if (highResAvailableSizes != null && highResAvailableSizes.length > 0) {
Size[] allSizes = new Size[availableSizes.length + highResAvailableSizes.length];
System.arraycopy(availableSizes, 0, allSizes, 0, availableSizes.length);
System.arraycopy(highResAvailableSizes, 0, allSizes, availableSizes.length, highResAvailableSizes.length);
availableSizes = allSizes;
}
if (VERBOSE)
Log.v(TAG, "Supported sizes are: " + Arrays.deepToString(availableSizes));
return availableSizes;
}
use of android.util.Size in project platform_frameworks_base by android.
the class CameraTestUtils method basicValidateJpegImage.
/**
* Simple validation of JPEG image size and format.
* <p>
* Only validate the image object sanity. It is fast, but doesn't actually
* check the buffer data. Assert is used here as it make no sense to
* continue the test if the jpeg image captured has some serious failures.
* </p>
*
* @param image The captured jpeg image
* @param expectedSize Expected capture jpeg size
*/
public static void basicValidateJpegImage(Image image, Size expectedSize) {
Size imageSz = new Size(image.getWidth(), image.getHeight());
assertTrue(String.format("Image size doesn't match (expected %s, actual %s) ", expectedSize.toString(), imageSz.toString()), expectedSize.equals(imageSz));
assertEquals("Image format should be JPEG", ImageFormat.JPEG, image.getFormat());
assertNotNull("Image plane shouldn't be null", image.getPlanes());
assertEquals("Image plane number should be 1", 1, image.getPlanes().length);
// Jpeg decoding validate was done in ImageReaderTest, no need to duplicate the test here.
}
use of android.util.Size in project platform_frameworks_base by android.
the class StaticMetadata method getAvailableSizesForFormatChecked.
/**
* Get available sizes for given format and direction, and whether to limit to slow or fast
* resolutions.
*
* @param format The format for the requested size array.
* @param direction The stream direction, input or output.
* @param fastSizes whether to include getOutputSizes() sizes (generally faster)
* @param slowSizes whether to include getHighResolutionOutputSizes() sizes (generally slower)
* @return The sizes of the given format, empty array if no available size is found.
*/
public Size[] getAvailableSizesForFormatChecked(int format, StreamDirection direction, boolean fastSizes, boolean slowSizes) {
Key<StreamConfigurationMap> key = CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP;
StreamConfigurationMap config = getValueFromKeyNonNull(key);
if (config == null) {
return new Size[0];
}
Size[] sizes = null;
switch(direction) {
case Output:
Size[] fastSizeList = null;
Size[] slowSizeList = null;
if (fastSizes) {
fastSizeList = config.getOutputSizes(format);
}
if (slowSizes) {
slowSizeList = config.getHighResolutionOutputSizes(format);
}
if (fastSizeList != null && slowSizeList != null) {
sizes = new Size[slowSizeList.length + fastSizeList.length];
System.arraycopy(fastSizeList, 0, sizes, 0, fastSizeList.length);
System.arraycopy(slowSizeList, 0, sizes, fastSizeList.length, slowSizeList.length);
} else if (fastSizeList != null) {
sizes = fastSizeList;
} else if (slowSizeList != null) {
sizes = slowSizeList;
}
break;
case Input:
sizes = config.getInputSizes(format);
break;
default:
throw new IllegalArgumentException("direction must be output or input");
}
if (sizes == null) {
sizes = new Size[0];
}
return sizes;
}
Aggregations