use of android.hardware.camera2.params.StreamConfigurationMap in project android_frameworks_base by crdroidandroid.
the class CameraConstrainedHighSpeedCaptureSessionImpl method createHighSpeedRequestList.
@Override
public List<CaptureRequest> createHighSpeedRequestList(CaptureRequest request) throws CameraAccessException {
if (request == null) {
throw new IllegalArgumentException("Input capture request must not be null");
}
Collection<Surface> outputSurfaces = request.getTargets();
Range<Integer> fpsRange = request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
StreamConfigurationMap config = mCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
SurfaceUtils.checkConstrainedHighSpeedSurfaces(outputSurfaces, fpsRange, config);
// Request list size: to limit the preview to 30fps, need use maxFps/30; to maximize
// the preview frame rate, should use maxBatch size for that high speed stream
// configuration. We choose the former for now.
int requestListSize = fpsRange.getUpper() / 30;
List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
// Prepare the Request builders: need carry over the request controls.
// First, create a request builder that will only include preview or recording target.
CameraMetadataNative requestMetadata = new CameraMetadataNative(request.getNativeCopy());
// Note that after this step, the requestMetadata is mutated (swapped) and can not be used
// for next request builder creation.
CaptureRequest.Builder singleTargetRequestBuilder = new CaptureRequest.Builder(requestMetadata, /*reprocess*/
false, CameraCaptureSession.SESSION_ID_NONE);
// Overwrite the capture intent to make sure a good value is set.
Iterator<Surface> iterator = outputSurfaces.iterator();
Surface firstSurface = iterator.next();
Surface secondSurface = null;
if (outputSurfaces.size() == 1 && SurfaceUtils.isSurfaceForHwVideoEncoder(firstSurface)) {
singleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_PREVIEW);
} else {
// Video only, or preview + video
singleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
}
singleTargetRequestBuilder.setPartOfCHSRequestList(/*partOfCHSList*/
true);
// Second, Create a request builder that will include both preview and recording targets.
CaptureRequest.Builder doubleTargetRequestBuilder = null;
if (outputSurfaces.size() == 2) {
// Have to create a new copy, the original one was mutated after a new
// CaptureRequest.Builder creation.
requestMetadata = new CameraMetadataNative(request.getNativeCopy());
doubleTargetRequestBuilder = new CaptureRequest.Builder(requestMetadata, /*reprocess*/
false, CameraCaptureSession.SESSION_ID_NONE);
doubleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
doubleTargetRequestBuilder.addTarget(firstSurface);
secondSurface = iterator.next();
doubleTargetRequestBuilder.addTarget(secondSurface);
doubleTargetRequestBuilder.setPartOfCHSRequestList(/*partOfCHSList*/
true);
// Make sure singleTargetRequestBuilder contains only recording surface for
// preview + recording case.
Surface recordingSurface = firstSurface;
if (!SurfaceUtils.isSurfaceForHwVideoEncoder(recordingSurface)) {
recordingSurface = secondSurface;
}
singleTargetRequestBuilder.addTarget(recordingSurface);
} else {
// Single output case: either recording or preview.
singleTargetRequestBuilder.addTarget(firstSurface);
}
// Generate the final request list.
for (int i = 0; i < requestListSize; i++) {
if (i == 0 && doubleTargetRequestBuilder != null) {
// First request should be recording + preview request
requestList.add(doubleTargetRequestBuilder.build());
} else {
requestList.add(singleTargetRequestBuilder.build());
}
}
return Collections.unmodifiableList(requestList);
}
use of android.hardware.camera2.params.StreamConfigurationMap in project android_frameworks_base by crdroidandroid.
the class CameraDeviceImpl method createConstrainedHighSpeedCaptureSession.
@Override
public void createConstrainedHighSpeedCaptureSession(List<Surface> outputs, android.hardware.camera2.CameraCaptureSession.StateCallback callback, Handler handler) throws CameraAccessException {
if (outputs == null || outputs.size() == 0 || outputs.size() > 2) {
throw new IllegalArgumentException("Output surface list must not be null and the size must be no more than 2");
}
StreamConfigurationMap config = getCharacteristics().get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
SurfaceUtils.checkConstrainedHighSpeedSurfaces(outputs, /*fpsRange*/
null, config);
List<OutputConfiguration> outConfigurations = new ArrayList<>(outputs.size());
for (Surface surface : outputs) {
outConfigurations.add(new OutputConfiguration(surface));
}
createCaptureSessionInternal(null, outConfigurations, callback, handler, /*isConstrainedHighSpeed*/
true);
}
use of android.hardware.camera2.params.StreamConfigurationMap in project android_frameworks_base by crdroidandroid.
the class CameraDeviceImpl method checkInputConfiguration.
private void checkInputConfiguration(InputConfiguration inputConfig) {
if (inputConfig != null) {
StreamConfigurationMap configMap = mCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
int[] inputFormats = configMap.getInputFormats();
boolean validFormat = false;
for (int format : inputFormats) {
if (format == inputConfig.getFormat()) {
validFormat = true;
}
}
if (validFormat == false) {
throw new IllegalArgumentException("input format " + inputConfig.getFormat() + " is not valid");
}
boolean validSize = false;
Size[] inputSizes = configMap.getInputSizes(inputConfig.getFormat());
for (Size s : inputSizes) {
if (inputConfig.getWidth() == s.getWidth() && inputConfig.getHeight() == s.getHeight()) {
validSize = true;
}
}
if (validSize == false) {
throw new IllegalArgumentException("input size " + inputConfig.getWidth() + "x" + inputConfig.getHeight() + " is not valid");
}
}
}
use of android.hardware.camera2.params.StreamConfigurationMap in project android_frameworks_base by crdroidandroid.
the class LegacyMetadataMapper method mapScalerStreamConfigs.
private static void mapScalerStreamConfigs(CameraMetadataNative m, Camera.Parameters p) {
ArrayList<StreamConfiguration> availableStreamConfigs = new ArrayList<>();
/*
* Implementation-defined (preview, recording, etc) -> use camera1 preview sizes
* YUV_420_888 cpu callbacks -> use camera1 preview sizes
* Other preview callbacks (CPU) -> use camera1 preview sizes
* JPEG still capture -> use camera1 still capture sizes
*
* Use platform-internal format constants here, since StreamConfigurationMap does the
* remapping to public format constants.
*/
List<Camera.Size> previewSizes = p.getSupportedPreviewSizes();
List<Camera.Size> jpegSizes = p.getSupportedPictureSizes();
/*
* Work-around for b/17589233:
* - Some HALs's largest preview size aspect ratio does not match the largest JPEG size AR
* - This causes a large amount of problems with focus/metering because it's relative to
* preview, making the difference between the JPEG and preview viewport inaccessible
* - This boils down to metering or focusing areas being "arbitrarily" cropped
* in the capture result.
* - Work-around the HAL limitations by removing all of the largest preview sizes
* until we get one with the same aspect ratio as the jpeg size.
*/
{
SizeAreaComparator areaComparator = new SizeAreaComparator();
// Sort preview to min->max
Collections.sort(previewSizes, areaComparator);
Camera.Size maxJpegSize = SizeAreaComparator.findLargestByArea(jpegSizes);
float jpegAspectRatio = maxJpegSize.width * 1.0f / maxJpegSize.height;
if (DEBUG) {
Log.v(TAG, String.format("mapScalerStreamConfigs - largest JPEG area %dx%d, AR=%f", maxJpegSize.width, maxJpegSize.height, jpegAspectRatio));
}
// Now remove preview sizes from the end (largest->smallest) until aspect ratio matches
while (!previewSizes.isEmpty()) {
// max is always at the end
int index = previewSizes.size() - 1;
Camera.Size size = previewSizes.get(index);
float previewAspectRatio = size.width * 1.0f / size.height;
if (Math.abs(jpegAspectRatio - previewAspectRatio) >= PREVIEW_ASPECT_RATIO_TOLERANCE) {
// Assume removing from end is O(1)
previewSizes.remove(index);
if (DEBUG) {
Log.v(TAG, String.format("mapScalerStreamConfigs - removed preview size %dx%d, AR=%f " + "was not the same", size.width, size.height, previewAspectRatio));
}
} else {
break;
}
}
if (previewSizes.isEmpty()) {
// Fall-back to the original faulty behavior, but at least work
Log.w(TAG, "mapScalerStreamConfigs - failed to find any preview size matching " + "JPEG aspect ratio " + jpegAspectRatio);
previewSizes = p.getSupportedPreviewSizes();
}
// Sort again, this time in descending order max->min
Collections.sort(previewSizes, Collections.reverseOrder(areaComparator));
}
appendStreamConfig(availableStreamConfigs, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, previewSizes);
appendStreamConfig(availableStreamConfigs, ImageFormat.YUV_420_888, previewSizes);
for (int format : p.getSupportedPreviewFormats()) {
if (ImageFormat.isPublicFormat(format) && format != ImageFormat.NV21) {
appendStreamConfig(availableStreamConfigs, format, previewSizes);
} else if (DEBUG) {
/*
* Do not add any formats unknown to us
* (since it would fail runtime checks in StreamConfigurationMap)
*/
Log.v(TAG, String.format("mapStreamConfigs - Skipping format %x", format));
}
}
appendStreamConfig(availableStreamConfigs, HAL_PIXEL_FORMAT_BLOB, p.getSupportedPictureSizes());
/*
* scaler.availableStreamConfigurations
*/
m.set(SCALER_AVAILABLE_STREAM_CONFIGURATIONS, availableStreamConfigs.toArray(new StreamConfiguration[0]));
/*
* scaler.availableMinFrameDurations
*/
// No frame durations available
m.set(SCALER_AVAILABLE_MIN_FRAME_DURATIONS, new StreamConfigurationDuration[0]);
StreamConfigurationDuration[] jpegStalls = new StreamConfigurationDuration[jpegSizes.size()];
int i = 0;
long longestStallDuration = -1;
for (Camera.Size s : jpegSizes) {
long stallDuration = calculateJpegStallDuration(s);
jpegStalls[i++] = new StreamConfigurationDuration(HAL_PIXEL_FORMAT_BLOB, s.width, s.height, stallDuration);
if (longestStallDuration < stallDuration) {
longestStallDuration = stallDuration;
}
}
/*
* scaler.availableStallDurations
*/
// Set stall durations for jpeg, other formats use default stall duration
m.set(SCALER_AVAILABLE_STALL_DURATIONS, jpegStalls);
/*
* sensor.info.maxFrameDuration
*/
m.set(SENSOR_INFO_MAX_FRAME_DURATION, longestStallDuration);
}
use of android.hardware.camera2.params.StreamConfigurationMap in project android_frameworks_base by crdroidandroid.
the class CameraMetadataNative method getStreamConfigurationMap.
private StreamConfigurationMap getStreamConfigurationMap() {
StreamConfiguration[] configurations = getBase(CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
StreamConfigurationDuration[] minFrameDurations = getBase(CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS);
StreamConfigurationDuration[] stallDurations = getBase(CameraCharacteristics.SCALER_AVAILABLE_STALL_DURATIONS);
StreamConfiguration[] depthConfigurations = getBase(CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS);
StreamConfigurationDuration[] depthMinFrameDurations = getBase(CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS);
StreamConfigurationDuration[] depthStallDurations = getBase(CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS);
HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = getBase(CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
ReprocessFormatsMap inputOutputFormatsMap = getBase(CameraCharacteristics.SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP);
int[] capabilities = getBase(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
boolean listHighResolution = false;
for (int capability : capabilities) {
if (capability == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE) {
listHighResolution = true;
break;
}
}
return new StreamConfigurationMap(configurations, minFrameDurations, stallDurations, depthConfigurations, depthMinFrameDurations, depthStallDurations, highSpeedVideoConfigurations, inputOutputFormatsMap, listHighResolution);
}
Aggregations