Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66b289cb authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add support for P210 format in various java apis" into main

parents 5f4f9302 8102ce11
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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
+9 −0
Original line number Diff line number Diff line
@@ -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"
+6 −3
Original line number Diff line number Diff line
@@ -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);
+133 −6
Original line number Diff line number Diff line
@@ -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)) {
        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;
            }
        }
    }