diff --git a/core/api/current.txt b/core/api/current.txt index f49ce1fd48a5b..2e4ec8949107e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -15006,6 +15006,7 @@ package android.graphics { field public static final int RGB_565 = 4; // 0x4 field public static final int UNKNOWN = 0; // 0x0 field public static final int Y8 = 538982489; // 0x20203859 + field public static final int YCBCR_P010 = 54; // 0x36 field public static final int YUV_420_888 = 35; // 0x23 field public static final int YUV_422_888 = 39; // 0x27 field public static final int YUV_444_888 = 40; // 0x28 diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java index a7d3f7980d376..5b79d76dd6b9e 100644 --- a/graphics/java/android/graphics/ImageFormat.java +++ b/graphics/java/android/graphics/ImageFormat.java @@ -174,6 +174,39 @@ public class ImageFormat { */ public static final int Y16 = 0x20363159; + /** + *

Android YUV P010 format.

+ * + * P010 is a 4:2:0 YCbCr semiplanar format comprised of a WxH Y plane + * followed immediately by a Wx(H/2) CbCr plane. Each sample is + * represented by a 16-bit little-endian value, with the lower 6 bits set + * to zero. + * + *

This format assumes + *

+ *

+ * + *
   stride_in_bytes = stride * 2 
+ *
   y_size = stride_in_bytes * height 
+ *
   cbcr_size = stride_in_bytes * (height / 2) 
+ *
   cb_offset = y_size 
+ *
   cr_offset = cb_offset + 2 
+ * + *

For example, the {@link android.media.Image} object can provide data + * in this format from a {@link android.hardware.camera2.CameraDevice} + * through a {@link android.media.ImageReader} object if this format is + * supported by {@link android.hardware.camera2.CameraDevice}.

+ * + * @see android.media.Image + * @see android.media.ImageReader + * @see android.hardware.camera2.CameraDevice + * + */ + public static final int YCBCR_P010 = 0x36; + /** * YCbCr format, used for video. * @@ -807,6 +840,8 @@ public class ImageFormat { case RAW_DEPTH: case RAW_SENSOR: return 16; + case YCBCR_P010: + return 20; case RAW_DEPTH10: case RAW10: return 10; @@ -839,6 +874,7 @@ public class ImageFormat { case YUV_420_888: case YUV_422_888: case YUV_444_888: + case YCBCR_P010: case FLEX_RGB_888: case FLEX_RGBA_8888: case RAW_SENSOR: diff --git a/media/java/android/media/ImageUtils.java b/media/java/android/media/ImageUtils.java index d248f61f03ca3..7837d7e395997 100644 --- a/media/java/android/media/ImageUtils.java +++ b/media/java/android/media/ImageUtils.java @@ -45,6 +45,7 @@ class ImageUtils { case ImageFormat.YV12: case ImageFormat.YUV_420_888: case ImageFormat.NV21: + case ImageFormat.YCBCR_P010: return 3; case ImageFormat.NV16: return 2; @@ -225,6 +226,7 @@ class ImageUtils { case ImageFormat.RAW_SENSOR: case ImageFormat.RAW_PRIVATE: // round estimate, real size is unknown case ImageFormat.DEPTH16: + case ImageFormat.YCBCR_P010: estimatedBytePerPixel = 2.0; break; case PixelFormat.RGB_888: @@ -244,6 +246,7 @@ class ImageUtils { private static Size getEffectivePlaneSizeForImage(Image image, int planeIdx) { switch (image.getFormat()) { + case ImageFormat.YCBCR_P010: case ImageFormat.YV12: case ImageFormat.YUV_420_888: case ImageFormat.NV21: diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp index b6c47fca52f9b..ecd9cc1cd098e 100644 --- a/media/jni/android_media_Utils.cpp +++ b/media/jni/android_media_Utils.cpp @@ -69,6 +69,7 @@ bool isPossiblyYUV(PixelFormat format) { case HAL_PIXEL_FORMAT_RAW_OPAQUE: case HAL_PIXEL_FORMAT_BLOB: case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: + case HAL_PIXEL_FORMAT_YCBCR_P010: return false; case HAL_PIXEL_FORMAT_YV12: @@ -261,6 +262,32 @@ status_t getLockedImageInfo(LockedImage* buffer, int idx, pStride = 1; rStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16); break; + case HAL_PIXEL_FORMAT_YCBCR_P010: + if (buffer->height % 2 != 0) { + ALOGE("YCBCR_P010: height (%d) should be a multiple of 2", buffer->height); + return BAD_VALUE; + } + + if (buffer->width <= 0) { + ALOGE("YCBCR_P010: width (%d) should be a > 0", buffer->width); + return BAD_VALUE; + } + + if (buffer->height <= 0) { + ALOGE("YCBCR_P010: height (%d) should be a > 0", buffer->height); + return BAD_VALUE; + } + + ySize = (buffer->stride * 2) * buffer->height; + cSize = ySize / 2; + pStride = (idx == 0) ? 2 : 4; + cb = buffer->data + ySize; + cr = cb + 2; + + pData = (idx == 0) ? buffer->data : (idx == 1) ? cb : cr; + dataSize = (idx == 0) ? ySize : cSize; + rStride = buffer->stride * 2; + break; case HAL_PIXEL_FORMAT_Y8: // Single plane, 8bpp. LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);