diff options
| author | 2024-12-13 15:49:23 -0800 | |
|---|---|---|
| committer | 2024-12-13 15:49:23 -0800 | |
| commit | af4443ef0ec957dd1d82eb8218ae4e4ec4ffbe54 (patch) | |
| tree | 4671fbe7c15f34d4e3eb1c4ff31e1415398c9cf5 | |
| parent | 106d5b9454cbbf0d7288c9dc8d9d3d6a6b1b866c (diff) | |
| parent | 66b289cb9255432d412eda60dc8e555156a80aee (diff) | |
Merge "Add support for P210 format in various java apis" into main am: 66b289cb92
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/3271452
Change-Id: I8cfbaf785686cd49e6cc51817fb5c034d5b9e3a9
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
| -rw-r--r-- | media/java/android/media/Image.java | 9 | ||||
| -rw-r--r-- | media/java/android/media/ImageUtils.java | 9 | ||||
| -rw-r--r-- | media/java/android/media/MediaCodec.java | 9 | ||||
| -rw-r--r-- | media/jni/android_media_Utils.cpp | 139 |
4 files changed, 157 insertions, 9 deletions
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java index d6fe68253be6..486063ed5f6b 100644 --- a/media/java/android/media/Image.java +++ b/media/java/android/media/Image.java @@ -180,6 +180,15 @@ public abstract class Image implements AutoCloseable { * a semi-planar format, the Cb plane can also be treated as an interleaved Cb/Cr plane. * </td> * </tr> + * <tr> + * <td>{@link android.graphics.ImageFormat#YCBCR_P210 YCBCR_P210}</td> + * <td>3</td> + * <td>P210 is a 4:2:2 YCbCr semiplanar format comprised of a WxH Y plane + * followed by a WxH Cb and Cr planes. Each sample is represented by a 16-bit + * little-endian value, with the lower 6 bits set to zero. Since this is guaranteed to be + * a semi-planar format, the Cb plane can also be treated as an interleaved Cb/Cr plane. + * </td> + * </tr> * </table> * * @see android.graphics.ImageFormat diff --git a/media/java/android/media/ImageUtils.java b/media/java/android/media/ImageUtils.java index f4caad727407..83b056f2cb74 100644 --- a/media/java/android/media/ImageUtils.java +++ b/media/java/android/media/ImageUtils.java @@ -49,6 +49,7 @@ class ImageUtils { case ImageFormat.YUV_420_888: case ImageFormat.NV21: case ImageFormat.YCBCR_P010: + case ImageFormat.YCBCR_P210: return 3; case ImageFormat.NV16: return 2; @@ -88,6 +89,7 @@ class ImageUtils { switch(hardwareBufferFormat) { case HardwareBuffer.YCBCR_420_888: case HardwareBuffer.YCBCR_P010: + case HardwareBuffer.YCBCR_P210: return 3; case HardwareBuffer.RGBA_8888: case HardwareBuffer.RGBX_8888: @@ -269,6 +271,7 @@ class ImageUtils { case PixelFormat.RGBA_8888: case PixelFormat.RGBX_8888: case PixelFormat.RGBA_1010102: + case ImageFormat.YCBCR_P210: estimatedBytePerPixel = 4.0; break; default: @@ -318,6 +321,12 @@ class ImageUtils { return new Size(image.getWidth(), image.getHeight()); case ImageFormat.PRIVATE: return new Size(0, 0); + case ImageFormat.YCBCR_P210: + if (planeIdx == 0) { + return new Size(image.getWidth(), image.getHeight()); + } else { + return new Size(image.getWidth() / 2, image.getHeight()); + } default: if (Log.isLoggable(IMAGEUTILS_LOG_TAG, Log.VERBOSE)) { Log.v(IMAGEUTILS_LOG_TAG, "getEffectivePlaneSizeForImage() uses" diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 82e950365850..36f62da651db 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -6158,11 +6158,14 @@ final public class MediaCodec { buffer.limit(buffer.position() + Utils.divUp(bitDepth, 8) + (mHeight / vert - 1) * rowInc + (mWidth / horiz - 1) * colInc); mPlanes[ix] = new MediaPlane(buffer.slice(), rowInc, colInc); - if ((mFormat == ImageFormat.YUV_420_888 || mFormat == ImageFormat.YCBCR_P010) + if ((mFormat == ImageFormat.YUV_420_888 || mFormat == ImageFormat.YCBCR_P010 + || mFormat == ImageFormat.YCBCR_P210) && ix == 1) { cbPlaneOffset = planeOffset; } else if ((mFormat == ImageFormat.YUV_420_888 - || mFormat == ImageFormat.YCBCR_P010) && ix == 2) { + || mFormat == ImageFormat.YCBCR_P010 + || mFormat == ImageFormat.YCBCR_P210) + && ix == 2) { crPlaneOffset = planeOffset; } } @@ -6172,7 +6175,7 @@ final public class MediaCodec { } // Validate chroma semiplanerness. - if (mFormat == ImageFormat.YCBCR_P010) { + if (mFormat == ImageFormat.YCBCR_P010 || mFormat == ImageFormat.YCBCR_P210) { if (crPlaneOffset != cbPlaneOffset + planeOffsetInc) { throw new UnsupportedOperationException("Invalid plane offsets" + " cbPlaneOffset: " + cbPlaneOffset + " crPlaneOffset: " + crPlaneOffset); diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp index fbebbdcb8761..e8f8644a4503 100644 --- a/media/jni/android_media_Utils.cpp +++ b/media/jni/android_media_Utils.cpp @@ -17,13 +17,14 @@ // #define LOG_NDEBUG 0 #define LOG_TAG "AndroidMediaUtils" +#include "android_media_Utils.h" + +#include <aidl/android/hardware/graphics/common/PixelFormat.h> #include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h> #include <ui/GraphicBufferMapper.h> #include <ui/GraphicTypes.h> #include <utils/Log.h> -#include "android_media_Utils.h" - #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) ) // Must be in sync with the value in HeicCompositeStream.cpp @@ -33,6 +34,8 @@ namespace android { // -----------Utility functions used by ImageReader/Writer JNI----------------- +using AidlPixelFormat = aidl::android::hardware::graphics::common::PixelFormat; + enum { IMAGE_MAX_NUM_PLANES = 3, }; @@ -74,6 +77,7 @@ bool isPossiblyYUV(PixelFormat format) { case HAL_PIXEL_FORMAT_BLOB: case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: case HAL_PIXEL_FORMAT_YCBCR_P010: + case static_cast<int>(AidlPixelFormat::YCBCR_P210): return false; case HAL_PIXEL_FORMAT_YV12: @@ -105,6 +109,7 @@ bool isPossibly10BitYUV(PixelFormat format) { return false; case HAL_PIXEL_FORMAT_YCBCR_P010: + case static_cast<int>(AidlPixelFormat::YCBCR_P210): default: return true; } @@ -340,6 +345,47 @@ status_t getLockedImageInfo(LockedImage* buffer, int idx, 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 static_cast<int>(AidlPixelFormat::YCBCR_P210): + if (buffer->height % 2 != 0) { + ALOGE("YCBCR_P210: height (%d) should be a multiple of 2", buffer->height); + return BAD_VALUE; + } + + if (buffer->width <= 0) { + ALOGE("YCBCR_P210: width (%d) should be a > 0", buffer->width); + return BAD_VALUE; + } + + if (buffer->height <= 0) { + ALOGE("YCBCR_210: height (%d) should be a > 0", buffer->height); + return BAD_VALUE; + } + if (buffer->dataCb && buffer->dataCr) { + pData = (idx == 0) ? buffer->data : (idx == 1) ? buffer->dataCb : buffer->dataCr; + // only map until last pixel + if (idx == 0) { + pStride = 2; + rStride = buffer->stride; + dataSize = buffer->stride * (buffer->height - 1) + buffer->width * 2; + } else { + pStride = buffer->chromaStep; + rStride = buffer->chromaStride; + dataSize = buffer->chromaStride * (buffer->height - 1) + + buffer->chromaStep * (buffer->width / 2); + } + break; + } + + ySize = (buffer->stride * 2) * buffer->height; + cSize = ySize; + 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; @@ -544,6 +590,80 @@ static status_t extractP010Gralloc4PlaneLayout( return OK; } +static status_t extractP210Gralloc4PlaneLayout(sp<GraphicBuffer> buffer, void *pData, int format, + LockedImage *outputImage) { + using aidl::android::hardware::graphics::common::PlaneLayoutComponent; + using aidl::android::hardware::graphics::common::PlaneLayoutComponentType; + + GraphicBufferMapper &mapper = GraphicBufferMapper::get(); + std::vector<ui::PlaneLayout> planeLayouts; + status_t res = mapper.getPlaneLayouts(buffer->handle, &planeLayouts); + if (res != OK) { + return res; + } + constexpr int64_t Y_PLANE_COMPONENTS = int64_t(PlaneLayoutComponentType::Y); + constexpr int64_t CBCR_PLANE_COMPONENTS = + int64_t(PlaneLayoutComponentType::CB) | int64_t(PlaneLayoutComponentType::CR); + uint8_t *dataY = nullptr; + uint8_t *dataCb = nullptr; + uint8_t *dataCr = nullptr; + uint32_t strideY = 0; + uint32_t strideCbCr = 0; + for (const ui::PlaneLayout &layout : planeLayouts) { + ALOGV("gralloc4 plane: %s", layout.toString().c_str()); + int64_t components = 0; + for (const PlaneLayoutComponent &component : layout.components) { + if (component.sizeInBits != 10) { + return BAD_VALUE; + } + components |= component.type.value; + } + if (components == Y_PLANE_COMPONENTS) { + if (layout.sampleIncrementInBits != 16) { + return BAD_VALUE; + } + if (layout.components[0].offsetInBits != 6) { + return BAD_VALUE; + } + dataY = (uint8_t *)pData + layout.offsetInBytes; + strideY = layout.strideInBytes; + } else if (components == CBCR_PLANE_COMPONENTS) { + if (layout.sampleIncrementInBits != 32) { + return BAD_VALUE; + } + for (const PlaneLayoutComponent &component : layout.components) { + if (component.type.value == int64_t(PlaneLayoutComponentType::CB) && + component.offsetInBits != 6) { + return BAD_VALUE; + } + if (component.type.value == int64_t(PlaneLayoutComponentType::CR) && + component.offsetInBits != 22) { + return BAD_VALUE; + } + } + dataCb = (uint8_t *)pData + layout.offsetInBytes; + dataCr = (uint8_t *)pData + layout.offsetInBytes + 2; + strideCbCr = layout.strideInBytes; + } else { + return BAD_VALUE; + } + } + + outputImage->data = dataY; + outputImage->width = buffer->getWidth(); + outputImage->height = buffer->getHeight(); + outputImage->format = format; + outputImage->flexFormat = + static_cast<int>(AidlPixelFormat::YCBCR_P210); + outputImage->stride = strideY; + + outputImage->dataCb = dataCb; + outputImage->dataCr = dataCr; + outputImage->chromaStride = strideCbCr; + outputImage->chromaStep = 4; + return OK; +} + status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage, const Rect& rect, int fenceFd, LockedImage* outputImage) { ALOGV("%s: Try to lock the GraphicBuffer", __FUNCTION__); @@ -581,10 +701,17 @@ status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage, ALOGE("Lock buffer failed!"); return res; } - if (isPossibly10BitYUV(format) - && OK == extractP010Gralloc4PlaneLayout(buffer, pData, format, outputImage)) { - ALOGV("%s: Successfully locked the P010 image", __FUNCTION__); - return OK; + if (isPossibly10BitYUV(format)) { + if (format == HAL_PIXEL_FORMAT_YCBCR_P010 && + OK == extractP010Gralloc4PlaneLayout(buffer, pData, format, outputImage)) { + ALOGV("%s: Successfully locked the P010 image", __FUNCTION__); + return OK; + } else if ((format == + static_cast<int>(AidlPixelFormat::YCBCR_P210)) && + OK == extractP210Gralloc4PlaneLayout(buffer, pData, format, outputImage)) { + ALOGV("%s: Successfully locked the P210 image", __FUNCTION__); + return OK; + } } } |