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:
Emilian Peev
2019-01-04 17:48:31 +00:00
parent d345052a8f
commit 934ffa6d40
10 changed files with 238 additions and 28 deletions

View File

@@ -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

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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>();

View File

@@ -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:

View File

@@ -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. */

View File

@@ -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;
}

View File

@@ -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:

View File

@@ -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:

View File

@@ -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");