diff options
| -rw-r--r-- | media/TEST_MAPPING | 8 | ||||
| -rw-r--r-- | media/jni/android_media_ImageReader.cpp | 6 | ||||
| -rw-r--r-- | media/jni/android_media_Utils.cpp | 132 | ||||
| -rw-r--r-- | media/jni/android_media_Utils.h | 2 |
4 files changed, 147 insertions, 1 deletions
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING index a7ed09118817..4385a807774f 100644 --- a/media/TEST_MAPPING +++ b/media/TEST_MAPPING @@ -1,6 +1,14 @@ { "presubmit": [ { + "name": "CtsCameraTestCases", + "options" : [ + { + "include-filter": "android.hardware.camera2.cts.ImageReaderTest#testP010" + } + ] + }, + { "name": "GtsMediaTestCases", "options" : [ { diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp index 31e18178aee5..62c0d55951af 100644 --- a/media/jni/android_media_ImageReader.cpp +++ b/media/jni/android_media_ImageReader.cpp @@ -593,6 +593,12 @@ static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image, // (HAL_PIXEL_FORMAT_YCbCr_420_888) as HAL_PIXEL_FORMAT_YCbCr_420_888. ALOGV("%s: Treat buffer format to 0x%x as HAL_PIXEL_FORMAT_YCbCr_420_888", __FUNCTION__, bufferFormat); + } else if (imgReaderFmt == HAL_PIXEL_FORMAT_YCBCR_P010 && + isPossibly10BitYUV(bufferFormat)) { + // Treat formats that are compatible with flexible 10-bit YUV + // (HAL_PIXEL_FORMAT_YCBCR_P010) as HAL_PIXEL_FORMAT_YCBCR_P010. + ALOGV("%s: Treat buffer format to 0x%x as HAL_PIXEL_FORMAT_YCBCR_P010", + __FUNCTION__, bufferFormat); } else if (imgReaderFmt == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888) { // Using HAL_PIXEL_FORMAT_RGBA_8888 Gralloc buffers containing JPEGs to get around diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp index 39b560b393a9..f4a39b3469bb 100644 --- a/media/jni/android_media_Utils.cpp +++ b/media/jni/android_media_Utils.cpp @@ -17,7 +17,10 @@ // #define LOG_NDEBUG 0 #define LOG_TAG "AndroidMediaUtils" +#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h> #include <hardware/camera3.h> +#include <ui/GraphicBufferMapper.h> +#include <ui/GraphicTypes.h> #include <utils/Log.h> #include "android_media_Utils.h" @@ -81,6 +84,32 @@ bool isPossiblyYUV(PixelFormat format) { } } +bool isPossibly10BitYUV(PixelFormat format) { + switch (static_cast<int>(format)) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_RGB_888: + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_Y8: + case HAL_PIXEL_FORMAT_Y16: + case HAL_PIXEL_FORMAT_RAW16: + case HAL_PIXEL_FORMAT_RAW12: + case HAL_PIXEL_FORMAT_RAW10: + case HAL_PIXEL_FORMAT_RAW_OPAQUE: + case HAL_PIXEL_FORMAT_BLOB: + case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: + case HAL_PIXEL_FORMAT_YV12: + case HAL_PIXEL_FORMAT_YCbCr_420_888: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + return false; + + case HAL_PIXEL_FORMAT_YCBCR_P010: + default: + return true; + } +} + uint32_t Image_getBlobSize(LockedImage* buffer, bool usingRGBAOverride) { ALOGV("%s", __FUNCTION__); LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!"); @@ -279,6 +308,27 @@ status_t getLockedImageInfo(LockedImage* buffer, int idx, 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 / 2 - 1) + + buffer->chromaStep * (buffer->width / 2); + } + break; + } + ySize = (buffer->stride * 2) * buffer->height; cSize = ySize / 2; pStride = (idx == 0) ? 2 : 4; @@ -404,6 +454,7 @@ status_t getLockedImageInfo(LockedImage* buffer, int idx, rStride = buffer->stride * 3; break; default: + ALOGV("%s: unrecognized format 0x%x", __FUNCTION__, fmt); return BAD_VALUE; } @@ -415,6 +466,79 @@ status_t getLockedImageInfo(LockedImage* buffer, int idx, return OK; } +static status_t extractP010Gralloc4PlaneLayout( + 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 = HAL_PIXEL_FORMAT_YCBCR_P010; + 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__); @@ -433,11 +557,12 @@ status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage, status_t res; int format = buffer->getPixelFormat(); int flexFormat = format; + if (isPossiblyYUV(format)) { res = buffer->lockAsyncYCbCr(inUsage, rect, &ycbcr, fenceFd); if (res != OK) { - ALOGW("lockAsyncYCbCr failed with error %d", res); + ALOGW("lockAsyncYCbCr failed with error %d (format = 0x%x)", res, format); } pData = ycbcr.y; @@ -451,6 +576,11 @@ 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; + } } outputImage->data = reinterpret_cast<uint8_t*>(pData); diff --git a/media/jni/android_media_Utils.h b/media/jni/android_media_Utils.h index 12841c097943..4feb4f516f1e 100644 --- a/media/jni/android_media_Utils.h +++ b/media/jni/android_media_Utils.h @@ -35,6 +35,8 @@ bool isFormatOpaque(int format); bool isPossiblyYUV(PixelFormat format); +bool isPossibly10BitYUV(PixelFormat format); + status_t getLockedImageInfo(LockedImage* buffer, int idx, int32_t containerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride); |