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

Commit 39947040 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Support 10-bit YUV in color converter for thumbnails" into pi-dev

parents fb4e361a 4fdc4ce9
Loading
Loading
Loading
Loading
+110 −67
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@

#include "libyuv/convert_from.h"
#include "libyuv/video_common.h"

#include <functional>
#include <sys/time.h>

#define USE_LIBYUV
@@ -58,14 +58,16 @@ ColorConverter::~ColorConverter() {

bool ColorConverter::isValid() const {
    switch (mSrcFormat) {
        case OMX_COLOR_FormatYUV420Planar16:
            if (mDstFormat == OMX_COLOR_FormatYUV444Y410) {
                return true;
            }
            // fall-thru
        case OMX_COLOR_FormatYUV420Planar:
            return mDstFormat == OMX_COLOR_Format16bitRGB565
                    || mDstFormat == OMX_COLOR_Format32BitRGBA8888
                    || mDstFormat == OMX_COLOR_Format32bitBGRA8888;

        case OMX_COLOR_FormatYUV420Planar16:
            return mDstFormat == OMX_COLOR_FormatYUV444Y410;

        case OMX_COLOR_FormatCbYCrY:
        case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
        case OMX_COLOR_FormatYUV420SemiPlanar:
@@ -311,13 +313,40 @@ status_t ColorConverter::convertYUV420PlanarUseLibYUV(
    return OK;
}

void ColorConverter::writeToDst(
        void *dst_ptr, uint8_t *kAdjustedClip, bool uncropped,
        signed r1, signed g1, signed b1,
        signed r2, signed g2, signed b2) {
    switch (mDstFormat) {
std::function<void (void *, void *, void *, size_t,
                    signed *, signed *, signed *, signed *)>
getReadFromSrc(OMX_COLOR_FORMATTYPE srcFormat) {
    switch(srcFormat) {
    case OMX_COLOR_FormatYUV420Planar:
        return [](void *src_y, void *src_u, void *src_v, size_t x,
                  signed *y1, signed *y2, signed *u, signed *v) {
            *y1 = ((uint8_t*)src_y)[x] - 16;
            *y2 = ((uint8_t*)src_y)[x + 1] - 16;
            *u = ((uint8_t*)src_u)[x / 2] - 128;
            *v = ((uint8_t*)src_v)[x / 2] - 128;
        };
    case OMX_COLOR_FormatYUV420Planar16:
        return [](void *src_y, void *src_u, void *src_v, size_t x,
                signed *y1, signed *y2, signed *u, signed *v) {
            *y1 = (signed)(((uint16_t*)src_y)[x] >> 2) - 16;
            *y2 = (signed)(((uint16_t*)src_y)[x + 1] >> 2) - 16;
            *u = (signed)(((uint16_t*)src_u)[x / 2] >> 2) - 128;
            *v = (signed)(((uint16_t*)src_v)[x / 2] >> 2) - 128;
        };
    default:
        TRESPASS();
    }
    return nullptr;
}

std::function<void (void *, bool, signed, signed, signed, signed, signed, signed)>
getWriteToDst(OMX_COLOR_FORMATTYPE dstFormat, uint8_t *kAdjustedClip) {
    switch (dstFormat) {
    case OMX_COLOR_Format16bitRGB565:
    {
        return [kAdjustedClip](void *dst_ptr, bool uncropped,
                               signed r1, signed g1, signed b1,
                               signed r2, signed g2, signed b2) {
            uint32_t rgb1 =
                ((kAdjustedClip[r1] >> 3) << 11)
                | ((kAdjustedClip[g1] >> 2) << 5)
@@ -333,10 +362,13 @@ void ColorConverter::writeToDst(
            } else {
                *(uint16_t *)dst_ptr = rgb1;
            }
        break;
        };
    }
    case OMX_COLOR_Format32BitRGBA8888:
    {
        return [kAdjustedClip](void *dst_ptr, bool uncropped,
                               signed r1, signed g1, signed b1,
                               signed r2, signed g2, signed b2) {
            ((uint32_t *)dst_ptr)[0] =
                    (kAdjustedClip[r1])
                    | (kAdjustedClip[g1] << 8)
@@ -350,10 +382,13 @@ void ColorConverter::writeToDst(
                        | (kAdjustedClip[b2] << 16)
                        | (0xFF << 24);
            }
        break;
        };
    }
    case OMX_COLOR_Format32bitBGRA8888:
    {
        return [kAdjustedClip](void *dst_ptr, bool uncropped,
                               signed r1, signed g1, signed b1,
                               signed r2, signed g2, signed b2) {
            ((uint32_t *)dst_ptr)[0] =
                    (kAdjustedClip[b1])
                    | (kAdjustedClip[g1] << 8)
@@ -367,28 +402,31 @@ void ColorConverter::writeToDst(
                        | (kAdjustedClip[r2] << 16)
                        | (0xFF << 24);
            }
        break;
        };
    }
    default:
        break;
        TRESPASS();
    }
    return nullptr;
}

status_t ColorConverter::convertYUV420Planar(
        const BitmapParams &src, const BitmapParams &dst) {
    uint8_t *kAdjustedClip = initClip();

    auto readFromSrc = getReadFromSrc(mSrcFormat);
    auto writeToDst = getWriteToDst(mDstFormat, kAdjustedClip);

    uint8_t *dst_ptr = (uint8_t *)dst.mBits
            + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;

    const uint8_t *src_y =
        (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft;
    uint8_t *src_y = (uint8_t *)src.mBits
            + src.mCropTop * src.mStride + src.mCropLeft * src.mBpp;

    const uint8_t *src_u =
        (const uint8_t *)src.mBits + src.mStride * src.mHeight
        + (src.mCropTop / 2) * (src.mStride / 2) + src.mCropLeft / 2;
    uint8_t *src_u = (uint8_t *)src.mBits + src.mStride * src.mHeight
            + (src.mCropTop / 2) * (src.mStride / 2) + src.mCropLeft / 2 * src.mBpp;

    const uint8_t *src_v =
        src_u + (src.mStride / 2) * (src.mHeight / 2);
    uint8_t *src_v = src_u + (src.mStride / 2) * (src.mHeight / 2);

    for (size_t y = 0; y < src.cropHeight(); ++y) {
        for (size_t x = 0; x < src.cropWidth(); x += 2) {
@@ -410,11 +448,8 @@ status_t ColorConverter::convertYUV420Planar(

            // clip range -278 .. 535

            signed y1 = (signed)src_y[x] - 16;
            signed y2 = (signed)src_y[x + 1] - 16;

            signed u = (signed)src_u[x / 2] - 128;
            signed v = (signed)src_v[x / 2] - 128;
            signed y1, y2, u, v;
            readFromSrc(src_y, src_u, src_v, x, &y1, &y2, &u, &v);

            signed u_b = u * 517;
            signed u_g = -u * 100;
@@ -432,8 +467,7 @@ status_t ColorConverter::convertYUV420Planar(
            signed r2 = (tmp2 + v_r) / 256;

            bool uncropped = x + 1 < src.cropWidth();
            (void)writeToDst(dst_ptr + x * dst.mBpp,
                    kAdjustedClip, uncropped, r1, g1, b1, r2, g2, b2);
            writeToDst(dst_ptr + x * dst.mBpp, uncropped, r1, g1, b1, r2, g2, b2);
        }

        src_y += src.mStride;
@@ -449,6 +483,15 @@ status_t ColorConverter::convertYUV420Planar(
    return OK;
}

status_t ColorConverter::convertYUV420Planar16(
        const BitmapParams &src, const BitmapParams &dst) {
    if (mDstFormat == OMX_COLOR_FormatYUV444Y410) {
        return convertYUV420Planar16ToY410(src, dst);
    }

    return convertYUV420Planar(src, dst);
}

/*
 * Pack 10-bit YUV into RGBA_1010102.
 *
@@ -480,7 +523,7 @@ status_t ColorConverter::convertYUV420Planar(

#if !USE_NEON_Y410

status_t ColorConverter::convertYUV420Planar16(
status_t ColorConverter::convertYUV420Planar16ToY410(
        const BitmapParams &src, const BitmapParams &dst) {
    uint8_t *dst_ptr = (uint8_t *)dst.mBits
        + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
@@ -554,7 +597,7 @@ status_t ColorConverter::convertYUV420Planar16(

#else

status_t ColorConverter::convertYUV420Planar16(
status_t ColorConverter::convertYUV420Planar16ToY410(
        const BitmapParams &src, const BitmapParams &dst) {
    uint8_t *out = (uint8_t *)dst.mBits
        + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
+65 −7
Original line number Diff line number Diff line
@@ -79,13 +79,26 @@ void SoftwareRenderer::resetFormatIfChanged(
        cropBottomNew = heightNew - 1;
    }

    // The native window buffer format for high-bitdepth content could
    // depend on the dataspace also.
    android_dataspace dataSpace;
    bool dataSpaceChangedForPlanar16 = false;
    if (colorFormatNew == OMX_COLOR_FormatYUV420Planar16
            && format->findInt32("android._dataspace", (int32_t *)&dataSpace)
            && dataSpace != mDataSpace) {
        // Do not modify mDataSpace here, it's only modified at last
        // when we do native_window_set_buffers_data_space().
        dataSpaceChangedForPlanar16 = true;
    }

    if (static_cast<int32_t>(mColorFormat) == colorFormatNew &&
        mWidth == widthNew &&
        mHeight == heightNew &&
        mCropLeft == cropLeftNew &&
        mCropTop == cropTopNew &&
        mCropRight == cropRightNew &&
        mCropBottom == cropBottomNew) {
        mCropBottom == cropBottomNew &&
        !dataSpaceChangedForPlanar16) {
        // Nothing changed, no need to reset renderer.
        return;
    }
@@ -135,11 +148,16 @@ void SoftwareRenderer::resetFormatIfChanged(
            }
            case OMX_COLOR_FormatYUV420Planar16:
            {
                if (((dataSpace & HAL_DATASPACE_STANDARD_MASK) == HAL_DATASPACE_STANDARD_BT2020)
                 && ((dataSpace & HAL_DATASPACE_TRANSFER_MASK) == HAL_DATASPACE_TRANSFER_ST2084)) {
                    // Here we would convert OMX_COLOR_FormatYUV420Planar16 into
                    // OMX_COLOR_FormatYUV444Y410, and put it inside a buffer with
                    // format HAL_PIXEL_FORMAT_RGBA_1010102. Surfaceflinger will
                    // use render engine to convert it to RGB if needed.
                    halFormat = HAL_PIXEL_FORMAT_RGBA_1010102;
                } else {
                    halFormat = HAL_PIXEL_FORMAT_YV12;
                }
                bufWidth = (mCropWidth + 1) & ~1;
                bufHeight = (mCropHeight + 1) & ~1;
                break;
@@ -155,7 +173,7 @@ void SoftwareRenderer::resetFormatIfChanged(
        mConverter = new ColorConverter(
                mColorFormat, OMX_COLOR_Format16bitRGB565);
        CHECK(mConverter->isValid());
    } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar16) {
    } else if (halFormat == HAL_PIXEL_FORMAT_RGBA_1010102) {
        mConverter = new ColorConverter(
                mColorFormat, OMX_COLOR_FormatYUV444Y410);
        CHECK(mConverter->isValid());
@@ -295,6 +313,46 @@ std::list<FrameRenderTracker::Info> SoftwareRenderer::render(
            memcpy(dst_u, src_u, (mCropWidth + 1) / 2);
            memcpy(dst_v, src_v, (mCropWidth + 1) / 2);

            src_u += mWidth / 2;
            src_v += mWidth / 2;
            dst_u += dst_c_stride;
            dst_v += dst_c_stride;
        }
    } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar16) {
        const uint16_t *src_y = (const uint16_t *)data;
        const uint16_t *src_u = (const uint16_t *)data + mWidth * mHeight;
        const uint16_t *src_v = src_u + (mWidth / 2 * mHeight / 2);

        src_y += mCropLeft + mCropTop * mWidth;
        src_u += (mCropLeft + mCropTop * mWidth / 2) / 2;
        src_v += (mCropLeft + mCropTop * mWidth / 2) / 2;

        uint8_t *dst_y = (uint8_t *)dst;
        size_t dst_y_size = buf->stride * buf->height;
        size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
        size_t dst_c_size = dst_c_stride * buf->height / 2;
        uint8_t *dst_v = dst_y + dst_y_size;
        uint8_t *dst_u = dst_v + dst_c_size;

        dst_y += mCropTop * buf->stride + mCropLeft;
        dst_v += (mCropTop / 2) * dst_c_stride + mCropLeft / 2;
        dst_u += (mCropTop / 2) * dst_c_stride + mCropLeft / 2;

        for (int y = 0; y < mCropHeight; ++y) {
            for (int x = 0; x < mCropWidth; ++x) {
                dst_y[x] = (uint8_t)(src_y[x] >> 2);
            }

            src_y += mWidth;
            dst_y += buf->stride;
        }

        for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
            for (int x = 0; x < (mCropWidth + 1) / 2; ++x) {
                dst_u[x] = (uint8_t)(src_u[x] >> 2);
                dst_v[x] = (uint8_t)(src_v[x] >> 2);
            }

            src_u += mWidth / 2;
            src_v += mWidth / 2;
            dst_u += dst_c_stride;
+7 −5
Original line number Diff line number Diff line
@@ -75,10 +75,16 @@ private:
    status_t convertYUV420Planar(
            const BitmapParams &src, const BitmapParams &dst);

    status_t convertYUV420PlanarUseLibYUV(
            const BitmapParams &src, const BitmapParams &dst);

    status_t convertYUV420Planar16(
            const BitmapParams &src, const BitmapParams &dst);

    status_t convertYUV420PlanarUseLibYUV(
    status_t convertYUV420Planar16ToY410(
            const BitmapParams &src, const BitmapParams &dst);

    status_t convertYUV420Planar16ToRGB(
            const BitmapParams &src, const BitmapParams &dst);

    status_t convertQCOMYUV420SemiPlanar(
@@ -90,10 +96,6 @@ private:
    status_t convertTIYUV420PackedSemiPlanar(
            const BitmapParams &src, const BitmapParams &dst);

    void writeToDst(void *dst_ptr, uint8_t *kAdjustedClip, bool uncropped,
            signed r1, signed g1, signed b1,
            signed r2, signed g2, signed b2);

    ColorConverter(const ColorConverter &);
    ColorConverter &operator=(const ColorConverter &);
};