Camera: Add support for dynamic depth image format
The Jpeg image format must support additional dynamic depth metadata according to the new standard. Camera devices supporting non-exclusive depth map streams along with appropriate Jpeg output will include this new format by default. Bug: 109735087 Test: Camera CTS Change-Id: Id628466323a1ffbbdc7b44a5d15fe8df1cab8743
This commit is contained in:
@@ -14121,6 +14121,7 @@ package android.graphics {
|
||||
ctor public ImageFormat();
|
||||
method public static int getBitsPerPixel(int);
|
||||
field public static final int DEPTH16 = 1144402265; // 0x44363159
|
||||
field public static final int DEPTH_JPEG = 1768253795; // 0x69656963
|
||||
field public static final int DEPTH_POINT_CLOUD = 257; // 0x101
|
||||
field public static final int FLEX_RGBA_8888 = 42; // 0x2a
|
||||
field public static final int FLEX_RGB_888 = 41; // 0x29
|
||||
|
||||
@@ -3720,6 +3720,59 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
|
||||
public static final Key<android.hardware.camera2.params.RecommendedStreamConfiguration[]> DEPTH_AVAILABLE_RECOMMENDED_DEPTH_STREAM_CONFIGURATIONS =
|
||||
new Key<android.hardware.camera2.params.RecommendedStreamConfiguration[]>("android.depth.availableRecommendedDepthStreamConfigurations", android.hardware.camera2.params.RecommendedStreamConfiguration[].class);
|
||||
|
||||
/**
|
||||
* <p>The available dynamic depth dataspace stream
|
||||
* configurations that this camera device supports
|
||||
* (i.e. format, width, height, output/input stream).</p>
|
||||
* <p>These are output stream configurations for use with
|
||||
* dataSpace DYNAMIC_DEPTH. The configurations are
|
||||
* listed as <code>(format, width, height, input?)</code> tuples.</p>
|
||||
* <p>Only devices that support depth output for at least
|
||||
* the HAL_PIXEL_FORMAT_Y16 dense depth map along with
|
||||
* HAL_PIXEL_FORMAT_BLOB with the same size or size with
|
||||
* the same aspect ratio can have dynamic depth dataspace
|
||||
* stream configuration. {@link CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE android.depth.depthIsExclusive} also
|
||||
* needs to be set to FALSE.</p>
|
||||
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
|
||||
*
|
||||
* @see CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE
|
||||
* @hide
|
||||
*/
|
||||
public static final Key<android.hardware.camera2.params.StreamConfiguration[]> DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS =
|
||||
new Key<android.hardware.camera2.params.StreamConfiguration[]>("android.depth.availableDynamicDepthStreamConfigurations", android.hardware.camera2.params.StreamConfiguration[].class);
|
||||
|
||||
/**
|
||||
* <p>This lists the minimum frame duration for each
|
||||
* format/size combination for dynamic depth output streams.</p>
|
||||
* <p>This should correspond to the frame duration when only that
|
||||
* stream is active, with all processing (typically in android.*.mode)
|
||||
* set to either OFF or FAST.</p>
|
||||
* <p>When multiple streams are used in a request, the minimum frame
|
||||
* duration will be max(individual stream min durations).</p>
|
||||
* <p>The minimum frame duration of a stream (of a particular format, size)
|
||||
* is the same regardless of whether the stream is input or output.</p>
|
||||
* <p><b>Units</b>: (format, width, height, ns) x n</p>
|
||||
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
|
||||
* @hide
|
||||
*/
|
||||
public static final Key<android.hardware.camera2.params.StreamConfigurationDuration[]> DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS =
|
||||
new Key<android.hardware.camera2.params.StreamConfigurationDuration[]>("android.depth.availableDynamicDepthMinFrameDurations", android.hardware.camera2.params.StreamConfigurationDuration[].class);
|
||||
|
||||
/**
|
||||
* <p>This lists the maximum stall duration for each
|
||||
* output format/size combination for dynamic depth streams.</p>
|
||||
* <p>A stall duration is how much extra time would get added
|
||||
* to the normal minimum frame duration for a repeating request
|
||||
* that has streams with non-zero stall.</p>
|
||||
* <p>All dynamic depth output streams may have a nonzero stall
|
||||
* duration.</p>
|
||||
* <p><b>Units</b>: (format, width, height, ns) x n</p>
|
||||
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
|
||||
* @hide
|
||||
*/
|
||||
public static final Key<android.hardware.camera2.params.StreamConfigurationDuration[]> DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS =
|
||||
new Key<android.hardware.camera2.params.StreamConfigurationDuration[]>("android.depth.availableDynamicDepthStallDurations", android.hardware.camera2.params.StreamConfigurationDuration[].class);
|
||||
|
||||
/**
|
||||
* <p>String containing the ids of the underlying physical cameras.</p>
|
||||
* <p>For a logical camera, this is concatenation of all underlying physical camera ids.
|
||||
|
||||
@@ -1119,6 +1119,8 @@ public class CameraMetadataNative implements Parcelable {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Dynamic depth streams involve alot of SW processing and currently cannot be
|
||||
// recommended.
|
||||
StreamConfigurationMap map = null;
|
||||
switch (i) {
|
||||
case RecommendedStreamConfigurationMap.USECASE_PREVIEW:
|
||||
@@ -1127,28 +1129,44 @@ public class CameraMetadataNative implements Parcelable {
|
||||
map = new StreamConfigurationMap(scData.streamConfigurationArray,
|
||||
scData.minDurationArray, scData.stallDurationArray,
|
||||
/*depthconfiguration*/ null, /*depthminduration*/ null,
|
||||
/*depthstallduration*/ null, /*highspeedvideoconfigurations*/ null,
|
||||
/*depthstallduration*/ null,
|
||||
/*dynamicDepthConfigurations*/ null,
|
||||
/*dynamicDepthMinFrameDurations*/ null,
|
||||
/*dynamicDepthStallDurations*/ null,
|
||||
/*highspeedvideoconfigurations*/ null,
|
||||
/*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]);
|
||||
break;
|
||||
case RecommendedStreamConfigurationMap.USECASE_RECORD:
|
||||
map = new StreamConfigurationMap(scData.streamConfigurationArray,
|
||||
scData.minDurationArray, scData.stallDurationArray,
|
||||
/*depthconfiguration*/ null, /*depthminduration*/ null,
|
||||
/*depthstallduration*/ null, highSpeedVideoConfigurations,
|
||||
/*depthstallduration*/ null,
|
||||
/*dynamicDepthConfigurations*/ null,
|
||||
/*dynamicDepthMinFrameDurations*/ null,
|
||||
/*dynamicDepthStallDurations*/ null,
|
||||
highSpeedVideoConfigurations,
|
||||
/*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]);
|
||||
break;
|
||||
case RecommendedStreamConfigurationMap.USECASE_ZSL:
|
||||
map = new StreamConfigurationMap(scData.streamConfigurationArray,
|
||||
scData.minDurationArray, scData.stallDurationArray,
|
||||
depthScData.streamConfigurationArray, depthScData.minDurationArray,
|
||||
depthScData.stallDurationArray, /*highSpeedVideoConfigurations*/ null,
|
||||
depthScData.stallDurationArray,
|
||||
/*dynamicDepthConfigurations*/ null,
|
||||
/*dynamicDepthMinFrameDurations*/ null,
|
||||
/*dynamicDepthStallDurations*/ null,
|
||||
/*highSpeedVideoConfigurations*/ null,
|
||||
inputOutputFormatsMap, listHighResolution, supportsPrivate[i]);
|
||||
break;
|
||||
default:
|
||||
map = new StreamConfigurationMap(scData.streamConfigurationArray,
|
||||
scData.minDurationArray, scData.stallDurationArray,
|
||||
depthScData.streamConfigurationArray, depthScData.minDurationArray,
|
||||
depthScData.stallDurationArray, /*highSpeedVideoConfigurations*/ null,
|
||||
depthScData.stallDurationArray,
|
||||
/*dynamicDepthConfigurations*/ null,
|
||||
/*dynamicDepthMinFrameDurations*/ null,
|
||||
/*dynamicDepthStallDurations*/ null,
|
||||
/*highSpeedVideoConfigurations*/ null,
|
||||
/*inputOutputFormatsMap*/ null, listHighResolution, supportsPrivate[i]);
|
||||
}
|
||||
|
||||
@@ -1206,6 +1224,12 @@ public class CameraMetadataNative implements Parcelable {
|
||||
CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS);
|
||||
StreamConfigurationDuration[] depthStallDurations = getBase(
|
||||
CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS);
|
||||
StreamConfiguration[] dynamicDepthConfigurations = getBase(
|
||||
CameraCharacteristics.DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
|
||||
StreamConfigurationDuration[] dynamicDepthMinFrameDurations = getBase(
|
||||
CameraCharacteristics.DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS);
|
||||
StreamConfigurationDuration[] dynamicDepthStallDurations = getBase(
|
||||
CameraCharacteristics.DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS);
|
||||
HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = getBase(
|
||||
CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
|
||||
ReprocessFormatsMap inputOutputFormatsMap = getBase(
|
||||
@@ -1214,7 +1238,8 @@ public class CameraMetadataNative implements Parcelable {
|
||||
return new StreamConfigurationMap(
|
||||
configurations, minFrameDurations, stallDurations,
|
||||
depthConfigurations, depthMinFrameDurations, depthStallDurations,
|
||||
highSpeedVideoConfigurations, inputOutputFormatsMap,
|
||||
dynamicDepthConfigurations, dynamicDepthMinFrameDurations,
|
||||
dynamicDepthStallDurations, highSpeedVideoConfigurations, inputOutputFormatsMap,
|
||||
listHighResolution);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,13 +95,17 @@ public final class StreamConfigurationMap {
|
||||
StreamConfiguration[] depthConfigurations,
|
||||
StreamConfigurationDuration[] depthMinFrameDurations,
|
||||
StreamConfigurationDuration[] depthStallDurations,
|
||||
StreamConfiguration[] dynamicDepthConfigurations,
|
||||
StreamConfigurationDuration[] dynamicDepthMinFrameDurations,
|
||||
StreamConfigurationDuration[] dynamicDepthStallDurations,
|
||||
HighSpeedVideoConfiguration[] highSpeedVideoConfigurations,
|
||||
ReprocessFormatsMap inputOutputFormatsMap,
|
||||
boolean listHighResolution) {
|
||||
this(configurations, minFrameDurations, stallDurations,
|
||||
depthConfigurations, depthMinFrameDurations, depthStallDurations,
|
||||
highSpeedVideoConfigurations, inputOutputFormatsMap, listHighResolution,
|
||||
/*enforceImplementationDefined*/ true);
|
||||
dynamicDepthConfigurations, dynamicDepthMinFrameDurations,
|
||||
dynamicDepthStallDurations, highSpeedVideoConfigurations, inputOutputFormatsMap,
|
||||
listHighResolution, /*enforceImplementationDefined*/ true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,6 +135,9 @@ public final class StreamConfigurationMap {
|
||||
StreamConfiguration[] depthConfigurations,
|
||||
StreamConfigurationDuration[] depthMinFrameDurations,
|
||||
StreamConfigurationDuration[] depthStallDurations,
|
||||
StreamConfiguration[] dynamicDepthConfigurations,
|
||||
StreamConfigurationDuration[] dynamicDepthMinFrameDurations,
|
||||
StreamConfigurationDuration[] dynamicDepthStallDurations,
|
||||
HighSpeedVideoConfiguration[] highSpeedVideoConfigurations,
|
||||
ReprocessFormatsMap inputOutputFormatsMap,
|
||||
boolean listHighResolution,
|
||||
@@ -163,6 +170,19 @@ public final class StreamConfigurationMap {
|
||||
"depthStallDurations");
|
||||
}
|
||||
|
||||
if (dynamicDepthConfigurations == null) {
|
||||
mDynamicDepthConfigurations = new StreamConfiguration[0];
|
||||
mDynamicDepthMinFrameDurations = new StreamConfigurationDuration[0];
|
||||
mDynamicDepthStallDurations = new StreamConfigurationDuration[0];
|
||||
} else {
|
||||
mDynamicDepthConfigurations = checkArrayElementsNotNull(dynamicDepthConfigurations,
|
||||
"dynamicDepthConfigurations");
|
||||
mDynamicDepthMinFrameDurations = checkArrayElementsNotNull(
|
||||
dynamicDepthMinFrameDurations, "dynamicDepthMinFrameDurations");
|
||||
mDynamicDepthStallDurations = checkArrayElementsNotNull(dynamicDepthStallDurations,
|
||||
"dynamicDepthStallDurations");
|
||||
}
|
||||
|
||||
if (highSpeedVideoConfigurations == null) {
|
||||
mHighSpeedVideoConfigurations = new HighSpeedVideoConfiguration[0];
|
||||
} else {
|
||||
@@ -205,6 +225,15 @@ public final class StreamConfigurationMap {
|
||||
mDepthOutputFormats.put(config.getFormat(),
|
||||
mDepthOutputFormats.get(config.getFormat()) + 1);
|
||||
}
|
||||
for (StreamConfiguration config : mDynamicDepthConfigurations) {
|
||||
if (!config.isOutput()) {
|
||||
// Ignoring input configs
|
||||
continue;
|
||||
}
|
||||
|
||||
mDynamicDepthOutputFormats.put(config.getFormat(),
|
||||
mDynamicDepthOutputFormats.get(config.getFormat()) + 1);
|
||||
}
|
||||
|
||||
if (configurations != null && enforceImplementationDefined &&
|
||||
mOutputFormats.indexOfKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) < 0) {
|
||||
@@ -335,6 +364,8 @@ public final class StreamConfigurationMap {
|
||||
int dataspace = imageFormatToDataspace(format);
|
||||
if (dataspace == HAL_DATASPACE_DEPTH) {
|
||||
return mDepthOutputFormats.indexOfKey(internalFormat) >= 0;
|
||||
} else if (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) {
|
||||
return mDynamicDepthOutputFormats.indexOfKey(internalFormat) >= 0;
|
||||
} else {
|
||||
return getFormatsMap(/*output*/true).indexOfKey(internalFormat) >= 0;
|
||||
}
|
||||
@@ -446,7 +477,9 @@ public final class StreamConfigurationMap {
|
||||
boolean isFlexible = SurfaceUtils.isFlexibleConsumer(surface);
|
||||
|
||||
StreamConfiguration[] configs =
|
||||
surfaceDataspace != HAL_DATASPACE_DEPTH ? mConfigurations : mDepthConfigurations;
|
||||
surfaceDataspace == HAL_DATASPACE_DEPTH ? mDepthConfigurations :
|
||||
surfaceDataspace == HAL_DATASPACE_DYNAMIC_DEPTH ? mDynamicDepthConfigurations :
|
||||
mConfigurations;
|
||||
for (StreamConfiguration config : configs) {
|
||||
if (config.getFormat() == surfaceFormat && config.isOutput()) {
|
||||
// Matching format, either need exact size match, or a flexible consumer
|
||||
@@ -479,7 +512,9 @@ public final class StreamConfigurationMap {
|
||||
int dataspace = imageFormatToDataspace(format);
|
||||
|
||||
StreamConfiguration[] configs =
|
||||
dataspace != HAL_DATASPACE_DEPTH ? mConfigurations : mDepthConfigurations;
|
||||
dataspace == HAL_DATASPACE_DEPTH ? mDepthConfigurations :
|
||||
dataspace == HAL_DATASPACE_DYNAMIC_DEPTH ? mDynamicDepthConfigurations :
|
||||
mConfigurations;
|
||||
for (StreamConfiguration config : configs) {
|
||||
if ((config.getFormat() == internalFormat) && config.isOutput() &&
|
||||
config.getSize().equals(size)) {
|
||||
@@ -992,6 +1027,12 @@ public final class StreamConfigurationMap {
|
||||
Arrays.equals(mMinFrameDurations, other.mMinFrameDurations) &&
|
||||
Arrays.equals(mStallDurations, other.mStallDurations) &&
|
||||
Arrays.equals(mDepthConfigurations, other.mDepthConfigurations) &&
|
||||
Arrays.equals(mDepthMinFrameDurations, other.mDepthMinFrameDurations) &&
|
||||
Arrays.equals(mDepthStallDurations, other.mDepthStallDurations) &&
|
||||
Arrays.equals(mDynamicDepthConfigurations, other.mDynamicDepthConfigurations) &&
|
||||
Arrays.equals(mDynamicDepthMinFrameDurations,
|
||||
other.mDynamicDepthMinFrameDurations) &&
|
||||
Arrays.equals(mDynamicDepthStallDurations, other.mDynamicDepthStallDurations) &&
|
||||
Arrays.equals(mHighSpeedVideoConfigurations,
|
||||
other.mHighSpeedVideoConfigurations);
|
||||
}
|
||||
@@ -1005,9 +1046,10 @@ public final class StreamConfigurationMap {
|
||||
public int hashCode() {
|
||||
// XX: do we care about order?
|
||||
return HashCodeHelpers.hashCodeGeneric(
|
||||
mConfigurations, mMinFrameDurations,
|
||||
mStallDurations,
|
||||
mDepthConfigurations, mHighSpeedVideoConfigurations);
|
||||
mConfigurations, mMinFrameDurations, mStallDurations,
|
||||
mDepthConfigurations, mDepthMinFrameDurations, mDepthStallDurations,
|
||||
mDynamicDepthConfigurations, mDynamicDepthMinFrameDurations,
|
||||
mDynamicDepthStallDurations, mHighSpeedVideoConfigurations);
|
||||
}
|
||||
|
||||
// Check that the argument is supported by #getOutputFormats or #getInputFormats
|
||||
@@ -1022,6 +1064,10 @@ public final class StreamConfigurationMap {
|
||||
if (mDepthOutputFormats.indexOfKey(internalFormat) >= 0) {
|
||||
return format;
|
||||
}
|
||||
} else if (internalDataspace == HAL_DATASPACE_DYNAMIC_DEPTH) {
|
||||
if (mDynamicDepthOutputFormats.indexOfKey(internalFormat) >= 0) {
|
||||
return format;
|
||||
}
|
||||
} else {
|
||||
if (mAllOutputFormats.indexOfKey(internalFormat) >= 0) {
|
||||
return format;
|
||||
@@ -1245,6 +1291,7 @@ public final class StreamConfigurationMap {
|
||||
switch (format) {
|
||||
case ImageFormat.JPEG:
|
||||
case ImageFormat.DEPTH_POINT_CLOUD:
|
||||
case ImageFormat.DEPTH_JPEG:
|
||||
return HAL_PIXEL_FORMAT_BLOB;
|
||||
case ImageFormat.DEPTH16:
|
||||
return HAL_PIXEL_FORMAT_Y16;
|
||||
@@ -1264,6 +1311,7 @@ public final class StreamConfigurationMap {
|
||||
* <li>ImageFormat.JPEG => HAL_DATASPACE_V0_JFIF
|
||||
* <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_DATASPACE_DEPTH
|
||||
* <li>ImageFormat.DEPTH16 => HAL_DATASPACE_DEPTH
|
||||
* <li>ImageFormat.DEPTH_JPEG => HAL_DATASPACE_DYNAMIC_DEPTH
|
||||
* <li>others => HAL_DATASPACE_UNKNOWN
|
||||
* </ul>
|
||||
* </p>
|
||||
@@ -1293,6 +1341,8 @@ public final class StreamConfigurationMap {
|
||||
case ImageFormat.DEPTH16:
|
||||
case ImageFormat.RAW_DEPTH:
|
||||
return HAL_DATASPACE_DEPTH;
|
||||
case ImageFormat.DEPTH_JPEG:
|
||||
return HAL_DATASPACE_DYNAMIC_DEPTH;
|
||||
default:
|
||||
return HAL_DATASPACE_UNKNOWN;
|
||||
}
|
||||
@@ -1343,12 +1393,16 @@ public final class StreamConfigurationMap {
|
||||
SparseIntArray formatsMap =
|
||||
!output ? mInputFormats :
|
||||
dataspace == HAL_DATASPACE_DEPTH ? mDepthOutputFormats :
|
||||
dataspace == HAL_DATASPACE_DYNAMIC_DEPTH ? mDynamicDepthOutputFormats :
|
||||
highRes ? mHighResOutputFormats :
|
||||
mOutputFormats;
|
||||
|
||||
int sizesCount = formatsMap.get(format);
|
||||
if ( ((!output || dataspace == HAL_DATASPACE_DEPTH) && sizesCount == 0) ||
|
||||
(output && dataspace != HAL_DATASPACE_DEPTH && mAllOutputFormats.get(format) == 0)) {
|
||||
if ( ((!output || (dataspace == HAL_DATASPACE_DEPTH ||
|
||||
dataspace == HAL_DATASPACE_DYNAMIC_DEPTH)) && sizesCount == 0) ||
|
||||
(output && (dataspace != HAL_DATASPACE_DEPTH &&
|
||||
dataspace != HAL_DATASPACE_DYNAMIC_DEPTH) &&
|
||||
mAllOutputFormats.get(format) == 0)) {
|
||||
// Only throw if this is really not supported at all
|
||||
throw new IllegalArgumentException("format not available");
|
||||
}
|
||||
@@ -1357,9 +1411,13 @@ public final class StreamConfigurationMap {
|
||||
int sizeIndex = 0;
|
||||
|
||||
StreamConfiguration[] configurations =
|
||||
(dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : mConfigurations;
|
||||
(dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations :
|
||||
(dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? mDynamicDepthConfigurations :
|
||||
mConfigurations;
|
||||
StreamConfigurationDuration[] minFrameDurations =
|
||||
(dataspace == HAL_DATASPACE_DEPTH) ? mDepthMinFrameDurations : mMinFrameDurations;
|
||||
(dataspace == HAL_DATASPACE_DEPTH) ? mDepthMinFrameDurations :
|
||||
(dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? mDynamicDepthMinFrameDurations :
|
||||
mMinFrameDurations;
|
||||
|
||||
for (StreamConfiguration config : configurations) {
|
||||
int fmt = config.getFormat();
|
||||
@@ -1386,7 +1444,21 @@ public final class StreamConfigurationMap {
|
||||
}
|
||||
}
|
||||
|
||||
if (sizeIndex != sizesCount) {
|
||||
// Dynamic depth streams can have both fast and also high res modes.
|
||||
if ((sizeIndex != sizesCount) && (dataspace == HAL_DATASPACE_DYNAMIC_DEPTH)) {
|
||||
|
||||
if (sizeIndex > sizesCount) {
|
||||
throw new AssertionError(
|
||||
"Too many dynamic depth sizes (expected " + sizesCount + ", actual " +
|
||||
sizeIndex + ")");
|
||||
}
|
||||
|
||||
if (sizeIndex <= 0) {
|
||||
sizes = new Size[0];
|
||||
} else {
|
||||
sizes = Arrays.copyOf(sizes, sizeIndex);
|
||||
}
|
||||
} else if (sizeIndex != sizesCount) {
|
||||
throw new AssertionError(
|
||||
"Too few sizes (expected " + sizesCount + ", actual " + sizeIndex + ")");
|
||||
}
|
||||
@@ -1409,6 +1481,10 @@ public final class StreamConfigurationMap {
|
||||
for (int j = 0; j < mDepthOutputFormats.size(); j++) {
|
||||
formats[i++] = depthFormatToPublic(mDepthOutputFormats.keyAt(j));
|
||||
}
|
||||
if (mDynamicDepthOutputFormats.size() > 0) {
|
||||
// Only one publicly dynamic depth format is available.
|
||||
formats[i++] = ImageFormat.DEPTH_JPEG;
|
||||
}
|
||||
}
|
||||
if (formats.length != i) {
|
||||
throw new AssertionError("Too few formats " + i + ", expected " + formats.length);
|
||||
@@ -1451,11 +1527,13 @@ public final class StreamConfigurationMap {
|
||||
private StreamConfigurationDuration[] getDurations(int duration, int dataspace) {
|
||||
switch (duration) {
|
||||
case DURATION_MIN_FRAME:
|
||||
return (dataspace == HAL_DATASPACE_DEPTH) ?
|
||||
mDepthMinFrameDurations : mMinFrameDurations;
|
||||
return (dataspace == HAL_DATASPACE_DEPTH) ? mDepthMinFrameDurations :
|
||||
(dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ?
|
||||
mDynamicDepthMinFrameDurations : mMinFrameDurations;
|
||||
case DURATION_STALL:
|
||||
return (dataspace == HAL_DATASPACE_DEPTH) ?
|
||||
mDepthStallDurations : mStallDurations;
|
||||
return (dataspace == HAL_DATASPACE_DEPTH) ? mDepthStallDurations :
|
||||
(dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? mDynamicDepthStallDurations :
|
||||
mStallDurations;
|
||||
default:
|
||||
throw new IllegalArgumentException("duration was invalid");
|
||||
}
|
||||
@@ -1467,6 +1545,7 @@ public final class StreamConfigurationMap {
|
||||
int size = formatsMap.size();
|
||||
if (output) {
|
||||
size += mDepthOutputFormats.size();
|
||||
size += mDynamicDepthOutputFormats.size();
|
||||
}
|
||||
|
||||
return size;
|
||||
@@ -1486,10 +1565,11 @@ public final class StreamConfigurationMap {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isSupportedInternalConfiguration(int format, int dataspace,
|
||||
Size size) {
|
||||
private boolean isSupportedInternalConfiguration(int format, int dataspace, Size size) {
|
||||
StreamConfiguration[] configurations =
|
||||
(dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : mConfigurations;
|
||||
(dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations :
|
||||
(dataspace == HAL_DATASPACE_DYNAMIC_DEPTH) ? mDynamicDepthConfigurations :
|
||||
mConfigurations;
|
||||
|
||||
for (int i = 0; i < configurations.length; i++) {
|
||||
if (configurations[i].getFormat() == format &&
|
||||
@@ -1681,6 +1761,8 @@ public final class StreamConfigurationMap {
|
||||
return "DEPTH16";
|
||||
case ImageFormat.DEPTH_POINT_CLOUD:
|
||||
return "DEPTH_POINT_CLOUD";
|
||||
case ImageFormat.DEPTH_JPEG:
|
||||
return "DEPTH_JPEG";
|
||||
case ImageFormat.RAW_DEPTH:
|
||||
return "RAW_DEPTH";
|
||||
case ImageFormat.PRIVATE:
|
||||
@@ -1712,6 +1794,7 @@ public final class StreamConfigurationMap {
|
||||
(1 << HAL_DATASPACE_RANGE_SHIFT);
|
||||
|
||||
private static final int HAL_DATASPACE_DEPTH = 0x1000;
|
||||
private static final int HAL_DATASPACE_DYNAMIC_DEPTH = 0x1002;
|
||||
|
||||
private static final long DURATION_20FPS_NS = 50000000L;
|
||||
/**
|
||||
@@ -1728,6 +1811,10 @@ public final class StreamConfigurationMap {
|
||||
private final StreamConfigurationDuration[] mDepthMinFrameDurations;
|
||||
private final StreamConfigurationDuration[] mDepthStallDurations;
|
||||
|
||||
private final StreamConfiguration[] mDynamicDepthConfigurations;
|
||||
private final StreamConfigurationDuration[] mDynamicDepthMinFrameDurations;
|
||||
private final StreamConfigurationDuration[] mDynamicDepthStallDurations;
|
||||
|
||||
private final HighSpeedVideoConfiguration[] mHighSpeedVideoConfigurations;
|
||||
private final ReprocessFormatsMap mInputOutputFormatsMap;
|
||||
|
||||
@@ -1745,6 +1832,8 @@ public final class StreamConfigurationMap {
|
||||
private final SparseIntArray mInputFormats = new SparseIntArray();
|
||||
/** internal format -> num depth output sizes mapping, for HAL_DATASPACE_DEPTH */
|
||||
private final SparseIntArray mDepthOutputFormats = new SparseIntArray();
|
||||
/** internal format -> num dynamic depth output sizes mapping, for HAL_DATASPACE_DYNAMIC_DEPTH */
|
||||
private final SparseIntArray mDynamicDepthOutputFormats = new SparseIntArray();
|
||||
/** High speed video Size -> FPS range count mapping*/
|
||||
private final HashMap</*HighSpeedVideoSize*/Size, /*Count*/Integer> mHighSpeedVideoSizeMap =
|
||||
new HashMap<Size, Integer>();
|
||||
|
||||
@@ -131,6 +131,7 @@ int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f) {
|
||||
switch(f) {
|
||||
case PublicFormat::JPEG:
|
||||
case PublicFormat::DEPTH_POINT_CLOUD:
|
||||
case PublicFormat::DEPTH_JPEG:
|
||||
return HAL_PIXEL_FORMAT_BLOB;
|
||||
case PublicFormat::DEPTH16:
|
||||
return HAL_PIXEL_FORMAT_Y16;
|
||||
@@ -161,6 +162,8 @@ android_dataspace android_view_Surface_mapPublicFormatToHalDataspace(
|
||||
case PublicFormat::NV21:
|
||||
case PublicFormat::YV12:
|
||||
return HAL_DATASPACE_V0_JFIF;
|
||||
case PublicFormat::DEPTH_JPEG:
|
||||
return static_cast<android_dataspace> (HAL_DATASPACE_DYNAMIC_DEPTH);
|
||||
default:
|
||||
// Most formats map to UNKNOWN
|
||||
return HAL_DATASPACE_UNKNOWN;
|
||||
@@ -223,8 +226,12 @@ PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat(
|
||||
case HAL_DATASPACE_V0_JFIF:
|
||||
return PublicFormat::JPEG;
|
||||
default:
|
||||
// Assume otherwise-marked blobs are also JPEG
|
||||
return PublicFormat::JPEG;
|
||||
if (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_DYNAMIC_DEPTH)) {
|
||||
return PublicFormat::DEPTH_JPEG;
|
||||
} else {
|
||||
// Assume otherwise-marked blobs are also JPEG
|
||||
return PublicFormat::JPEG;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HAL_PIXEL_FORMAT_BGRA_8888:
|
||||
|
||||
@@ -57,7 +57,8 @@ enum class PublicFormat {
|
||||
YV12 = 0x32315659,
|
||||
Y8 = 0x20203859, // @hide
|
||||
Y16 = 0x20363159, // @hide
|
||||
DEPTH16 = 0x44363159
|
||||
DEPTH16 = 0x44363159,
|
||||
DEPTH_JPEG = 0x69656963,
|
||||
};
|
||||
|
||||
/* Gets the underlying ANativeWindow for a Surface. */
|
||||
|
||||
@@ -182,6 +182,14 @@ public class ImageFormat {
|
||||
*/
|
||||
public static final int JPEG = 0x100;
|
||||
|
||||
/**
|
||||
* Depth augmented compressed JPEG format.
|
||||
*
|
||||
* <p>JPEG compressed main image along with XMP embedded depth metadata
|
||||
* following ISO 16684-1:2011(E).</p>
|
||||
*/
|
||||
public static final int DEPTH_JPEG = 0x69656963;
|
||||
|
||||
/**
|
||||
* <p>Multi-plane Android YUV 420 format</p>
|
||||
*
|
||||
@@ -787,6 +795,7 @@ public class ImageFormat {
|
||||
case PRIVATE:
|
||||
case RAW_DEPTH:
|
||||
case Y8:
|
||||
case DEPTH_JPEG:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -834,6 +834,7 @@ public class ImageReader implements AutoCloseable {
|
||||
case ImageFormat.JPEG:
|
||||
case ImageFormat.DEPTH_POINT_CLOUD:
|
||||
case ImageFormat.RAW_PRIVATE:
|
||||
case ImageFormat.DEPTH_JPEG:
|
||||
width = ImageReader.this.getWidth();
|
||||
break;
|
||||
default:
|
||||
@@ -850,6 +851,7 @@ public class ImageReader implements AutoCloseable {
|
||||
case ImageFormat.JPEG:
|
||||
case ImageFormat.DEPTH_POINT_CLOUD:
|
||||
case ImageFormat.RAW_PRIVATE:
|
||||
case ImageFormat.DEPTH_JPEG:
|
||||
height = ImageReader.this.getHeight();
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -63,6 +63,7 @@ class ImageUtils {
|
||||
case ImageFormat.DEPTH16:
|
||||
case ImageFormat.DEPTH_POINT_CLOUD:
|
||||
case ImageFormat.RAW_DEPTH:
|
||||
case ImageFormat.DEPTH_JPEG:
|
||||
return 1;
|
||||
case ImageFormat.PRIVATE:
|
||||
return 0;
|
||||
@@ -192,6 +193,7 @@ class ImageUtils {
|
||||
// 10x compression from RGB_888
|
||||
case ImageFormat.JPEG:
|
||||
case ImageFormat.DEPTH_POINT_CLOUD:
|
||||
case ImageFormat.DEPTH_JPEG:
|
||||
estimatedBytePerPixel = 0.3;
|
||||
break;
|
||||
case ImageFormat.Y8:
|
||||
|
||||
@@ -857,7 +857,7 @@ public class CameraTestUtils extends Assert {
|
||||
// JPEG doesn't have pixelstride and rowstride, treat it as 1D buffer.
|
||||
// Same goes for DEPTH_POINT_CLOUD
|
||||
if (format == ImageFormat.JPEG || format == ImageFormat.DEPTH_POINT_CLOUD ||
|
||||
format == ImageFormat.RAW_PRIVATE) {
|
||||
format == ImageFormat.DEPTH_JPEG || format == ImageFormat.RAW_PRIVATE) {
|
||||
buffer = planes[0].getBuffer();
|
||||
assertNotNull("Fail to get jpeg or depth ByteBuffer", buffer);
|
||||
data = new byte[buffer.remaining()];
|
||||
@@ -940,6 +940,7 @@ public class CameraTestUtils extends Assert {
|
||||
case ImageFormat.RAW_PRIVATE:
|
||||
case ImageFormat.DEPTH16:
|
||||
case ImageFormat.DEPTH_POINT_CLOUD:
|
||||
case ImageFormat.DEPTH_JPEG:
|
||||
assertEquals("JPEG/RAW/depth Images should have one plane", 1, planes.length);
|
||||
break;
|
||||
default:
|
||||
@@ -1363,6 +1364,9 @@ public class CameraTestUtils extends Assert {
|
||||
case ImageFormat.RAW_PRIVATE:
|
||||
validateRawPrivateData(data, width, height, image.getTimestamp(), filePath);
|
||||
break;
|
||||
case ImageFormat.DEPTH_JPEG:
|
||||
validateDepthJpegData(data, width, height, format, image.getTimestamp(), filePath);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unsupported format for validation: "
|
||||
+ format);
|
||||
@@ -1528,6 +1532,23 @@ public class CameraTestUtils extends Assert {
|
||||
|
||||
}
|
||||
|
||||
private static void validateDepthJpegData(byte[] depthData, int width, int height, int format,
|
||||
long ts, String filePath) {
|
||||
|
||||
if (VERBOSE) Log.v(TAG, "Validating depth jpeg data");
|
||||
|
||||
// Can't validate size since it is variable
|
||||
|
||||
if (DEBUG && filePath != null) {
|
||||
String fileName =
|
||||
filePath + "/" + width + "x" + height + "_" + ts / 1e6 + ".jpg";
|
||||
dumpFile(fileName, depthData);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public static <T> T getValueNotNull(CaptureResult result, CaptureResult.Key<T> key) {
|
||||
if (result == null) {
|
||||
throw new IllegalArgumentException("Result must not be null");
|
||||
|
||||
Reference in New Issue
Block a user