use of android.hardware.camera2.impl.CameraMetadataNative 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.impl.CameraMetadataNative in project android_frameworks_base by crdroidandroid.
the class LegacyMetadataMapper method createRequestTemplate.
/**
* Create a request template
*
* @param c a non-{@code null} camera characteristics for this camera
* @param templateId a non-negative template ID
*
* @return a non-{@code null} request template
*
* @throws IllegalArgumentException if {@code templateId} was invalid
*
* @see android.hardware.camera2.CameraDevice#TEMPLATE_MANUAL
*/
public static CameraMetadataNative createRequestTemplate(CameraCharacteristics c, int templateId) {
if (!ArrayUtils.contains(sAllowedTemplates, templateId)) {
throw new IllegalArgumentException("templateId out of range");
}
CameraMetadataNative m = new CameraMetadataNative();
/*
* NOTE: If adding new code here and it needs to query the static info,
* query the camera characteristics, so we can reuse this for api2 code later
* to create our own templates in the framework
*/
/*
* control.*
*/
// control.awbMode
m.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO);
// AWB is always unconditionally available in API1 devices
// control.aeAntibandingMode
m.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, CONTROL_AE_ANTIBANDING_MODE_AUTO);
// control.aeExposureCompensation
m.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);
// control.aeLock
m.set(CaptureRequest.CONTROL_AE_LOCK, false);
// control.aePrecaptureTrigger
m.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);
// control.afTrigger
m.set(CaptureRequest.CONTROL_AF_TRIGGER, CONTROL_AF_TRIGGER_IDLE);
// control.awbMode
m.set(CaptureRequest.CONTROL_AWB_MODE, CONTROL_AWB_MODE_AUTO);
// control.awbLock
m.set(CaptureRequest.CONTROL_AWB_LOCK, false);
// control.aeRegions, control.awbRegions, control.afRegions
{
Rect activeArray = c.get(SENSOR_INFO_ACTIVE_ARRAY_SIZE);
MeteringRectangle[] activeRegions = new MeteringRectangle[] { new MeteringRectangle(/*x*/
0, /*y*/
0, /*width*/
activeArray.width() - 1, /*height*/
activeArray.height() - 1, /*weight*/
0) };
m.set(CaptureRequest.CONTROL_AE_REGIONS, activeRegions);
m.set(CaptureRequest.CONTROL_AWB_REGIONS, activeRegions);
m.set(CaptureRequest.CONTROL_AF_REGIONS, activeRegions);
}
// control.captureIntent
{
int captureIntent;
switch(templateId) {
case CameraDevice.TEMPLATE_PREVIEW:
captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW;
break;
case CameraDevice.TEMPLATE_STILL_CAPTURE:
captureIntent = CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
break;
case CameraDevice.TEMPLATE_RECORD:
captureIntent = CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
break;
default:
// Can't get anything else since it's guarded by the IAE check
throw new AssertionError("Impossible; keep in sync with sAllowedTemplates");
}
m.set(CaptureRequest.CONTROL_CAPTURE_INTENT, captureIntent);
}
// control.aeMode
m.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
// AE is always unconditionally available in API1 devices
// control.mode
m.set(CaptureRequest.CONTROL_MODE, CONTROL_MODE_AUTO);
// control.afMode
{
Float minimumFocusDistance = c.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE);
int afMode;
if (minimumFocusDistance != null && minimumFocusDistance == LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS) {
// Cannot control auto-focus with fixed-focus cameras
afMode = CameraMetadata.CONTROL_AF_MODE_OFF;
} else {
// If a minimum focus distance is reported; the camera must have AF
afMode = CameraMetadata.CONTROL_AF_MODE_AUTO;
if (templateId == CameraDevice.TEMPLATE_RECORD || templateId == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
if (ArrayUtils.contains(c.get(CONTROL_AF_AVAILABLE_MODES), CONTROL_AF_MODE_CONTINUOUS_VIDEO)) {
afMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO;
}
} else if (templateId == CameraDevice.TEMPLATE_PREVIEW || templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) {
if (ArrayUtils.contains(c.get(CONTROL_AF_AVAILABLE_MODES), CONTROL_AF_MODE_CONTINUOUS_PICTURE)) {
afMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
}
}
}
if (DEBUG) {
Log.v(TAG, "createRequestTemplate (templateId=" + templateId + ")," + " afMode=" + afMode + ", minimumFocusDistance=" + minimumFocusDistance);
}
m.set(CaptureRequest.CONTROL_AF_MODE, afMode);
}
{
// control.aeTargetFpsRange
Range<Integer>[] availableFpsRange = c.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
// Pick FPS range with highest max value, tiebreak on higher min value
Range<Integer> bestRange = availableFpsRange[0];
for (Range<Integer> r : availableFpsRange) {
if (bestRange.getUpper() < r.getUpper()) {
bestRange = r;
} else if (bestRange.getUpper() == r.getUpper() && bestRange.getLower() < r.getLower()) {
bestRange = r;
}
}
m.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, bestRange);
}
// control.sceneMode -- DISABLED is always available
m.set(CaptureRequest.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_DISABLED);
/*
* statistics.*
*/
// statistics.faceDetectMode
m.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, STATISTICS_FACE_DETECT_MODE_OFF);
/*
* flash.*
*/
// flash.mode
m.set(CaptureRequest.FLASH_MODE, FLASH_MODE_OFF);
/*
* noiseReduction.*
*/
if (templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) {
m.set(CaptureRequest.NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_HIGH_QUALITY);
} else {
m.set(CaptureRequest.NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_FAST);
}
/*
* colorCorrection.*
*/
if (templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) {
m.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE, COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY);
} else {
m.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE, COLOR_CORRECTION_ABERRATION_MODE_FAST);
}
/*
* lens.*
*/
// lens.focalLength
m.set(CaptureRequest.LENS_FOCAL_LENGTH, c.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS)[0]);
/*
* jpeg.*
*/
// jpeg.thumbnailSize - set smallest non-zero size if possible
Size[] sizes = c.get(CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES);
m.set(CaptureRequest.JPEG_THUMBNAIL_SIZE, (sizes.length > 1) ? sizes[1] : sizes[0]);
// TODO: map other request template values
return m;
}
use of android.hardware.camera2.impl.CameraMetadataNative 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.impl.CameraMetadataNative in project android_frameworks_base by crdroidandroid.
the class LegacyFaceDetectMapper method mapResultFaces.
/**
* Update the {@code result} camera metadata map with the new value for the
* {@code statistics.faces} and {@code statistics.faceDetectMode}.
*
* <p>Face detect callbacks are processed in the background, and each call to
* {@link #mapResultFaces} will have the latest faces as reflected by the camera1 callbacks.</p>
*
* <p>If the scene mode was set to {@code FACE_PRIORITY} but face detection is disabled,
* the camera will still run face detection in the background, but no faces will be reported
* in the capture result.</p>
*
* @param result a non-{@code null} result
* @param legacyRequest a non-{@code null} request (read-only)
*/
public void mapResultFaces(CameraMetadataNative result, LegacyRequest legacyRequest) {
checkNotNull(result, "result must not be null");
checkNotNull(legacyRequest, "legacyRequest must not be null");
Camera.Face[] faces, previousFaces;
int fdMode;
boolean fdScenePriority;
synchronized (mLock) {
fdMode = mFaceDetectReporting ? STATISTICS_FACE_DETECT_MODE_SIMPLE : STATISTICS_FACE_DETECT_MODE_OFF;
if (mFaceDetectReporting) {
faces = mFaces;
} else {
faces = null;
}
fdScenePriority = mFaceDetectScenePriority;
previousFaces = mFacesPrev;
mFacesPrev = faces;
}
CameraCharacteristics characteristics = legacyRequest.characteristics;
CaptureRequest request = legacyRequest.captureRequest;
Size previewSize = legacyRequest.previewSize;
Camera.Parameters params = legacyRequest.parameters;
Rect activeArray = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
ZoomData zoomData = ParameterUtils.convertScalerCropRegion(activeArray, request.get(CaptureRequest.SCALER_CROP_REGION), previewSize, params);
List<Face> convertedFaces = new ArrayList<>();
if (faces != null) {
for (Camera.Face face : faces) {
if (face != null) {
convertedFaces.add(ParameterUtils.convertFaceFromLegacy(face, activeArray, zoomData));
} else {
Log.w(TAG, "mapResultFaces - read NULL face from camera1 device");
}
}
}
if (DEBUG && previousFaces != faces) {
// Log only in verbose and IF the faces changed
Log.v(TAG, "mapResultFaces - changed to " + ListUtils.listToString(convertedFaces));
}
result.set(CaptureResult.STATISTICS_FACES, convertedFaces.toArray(new Face[0]));
result.set(CaptureResult.STATISTICS_FACE_DETECT_MODE, fdMode);
// Override scene mode with FACE_PRIORITY if the request was using FACE_PRIORITY
if (fdScenePriority) {
result.set(CaptureResult.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_FACE_PRIORITY);
}
}
use of android.hardware.camera2.impl.CameraMetadataNative in project android_frameworks_base by crdroidandroid.
the class CameraDeviceUserShim method createDefaultRequest.
@Override
public CameraMetadataNative createDefaultRequest(int templateId) {
if (DEBUG) {
Log.d(TAG, "createDefaultRequest called.");
}
if (mLegacyDevice.isClosed()) {
String err = "Cannot create default request, device has been closed.";
Log.e(TAG, err);
throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
CameraMetadataNative template;
try {
template = LegacyMetadataMapper.createRequestTemplate(mCameraCharacteristics, templateId);
} catch (IllegalArgumentException e) {
String err = "createDefaultRequest - invalid templateId specified";
Log.e(TAG, err);
throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
}
return template;
}
Aggregations