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

Commit 789d5b07 authored by Wonsik Kim's avatar Wonsik Kim Committed by Gerrit Code Review
Browse files

Merge "sfplugin utils: expand libyuv coverage"

parents 5b346dea a38fdf2e
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -33,11 +33,13 @@ cc_library {
        "libcodec2_vndk",
        "libcodec2_vndk",
        "libcutils",
        "libcutils",
        "liblog",
        "liblog",
        "libnativewindow",
        "libstagefright_foundation",
        "libstagefright_foundation",
        "libutils",
        "libutils",
    ],
    ],


    static_libs: [
    static_libs: [
        "libarect",
        "libyuv_static",
        "libyuv_static",
    ],
    ],


+174 −32
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@
#include <list>
#include <list>
#include <mutex>
#include <mutex>


#include <android/hardware_buffer.h>
#include <media/hardware/HardwareAPI.h>
#include <media/hardware/HardwareAPI.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/foundation/AUtils.h>


@@ -136,31 +137,56 @@ status_t ImageCopy(uint8_t *imgBase, const MediaImage2 *img, const C2GraphicView
    int width = view.crop().width;
    int width = view.crop().width;
    int height = view.crop().height;
    int height = view.crop().height;


    if ((IsNV12(view) && IsI420(img)) || (IsI420(view) && IsNV12(img))) {
    if (IsNV12(view)) {
        // Take shortcuts to use libyuv functions between NV12 and I420 conversion.
        if (IsNV12(img)) {
        if (IsNV12(view) && IsI420(img)) {
            libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
            libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height / 2);
            return OK;
        } else if (IsNV21(img)) {
            if (!libyuv::NV21ToNV12(src_y, src_stride_y, src_u, src_stride_u,
                                    dst_y, dst_stride_y, dst_v, dst_stride_v, width, height)) {
                return OK;
            }
        } else if (IsI420(img)) {
            if (!libyuv::NV12ToI420(src_y, src_stride_y, src_u, src_stride_u, dst_y, dst_stride_y,
            if (!libyuv::NV12ToI420(src_y, src_stride_y, src_u, src_stride_u, dst_y, dst_stride_y,
                                    dst_u, dst_stride_u, dst_v, dst_stride_v, width, height)) {
                                    dst_u, dst_stride_u, dst_v, dst_stride_v, width, height)) {
                return OK;
                return OK;
            }
            }
        } else {
        }
            if (!libyuv::I420ToNV12(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
    } else if (IsNV21(view)) {
        if (IsNV12(img)) {
            if (!libyuv::NV21ToNV12(src_y, src_stride_y, src_v, src_stride_v,
                                    dst_y, dst_stride_y, dst_u, dst_stride_u, width, height)) {
                                    dst_y, dst_stride_y, dst_u, dst_stride_u, width, height)) {
                return OK;
                return OK;
            }
            }
        } else if (IsNV21(img)) {
            libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
            libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width, height / 2);
            return OK;
        } else if (IsI420(img)) {
            if (!libyuv::NV21ToI420(src_y, src_stride_y, src_v, src_stride_v, dst_y, dst_stride_y,
                                    dst_u, dst_stride_u, dst_v, dst_stride_v, width, height)) {
                return OK;
            }
            }
        }
        }
    if (IsNV12(view) && IsNV12(img)) {
    } else if (IsI420(view)) {
        libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
        if (IsNV12(img)) {
        libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height / 2);
            if (!libyuv::I420ToNV12(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
                                    dst_y, dst_stride_y, dst_u, dst_stride_u, width, height)) {
                return OK;
                return OK;
            }
            }
    if (IsI420(view) && IsI420(img)) {
        } else if (IsNV21(img)) {
            if (!libyuv::I420ToNV21(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
                                    dst_y, dst_stride_y, dst_v, dst_stride_v, width, height)) {
                return OK;
            }
        } else if (IsI420(img)) {
            libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
            libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
            libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width / 2, height / 2);
            libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width / 2, height / 2);
            libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width / 2, height / 2);
            libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width / 2, height / 2);
            return OK;
            return OK;
        }
        }
    }
    return _ImageCopy<true>(view, img, imgBase);
    return _ImageCopy<true>(view, img, imgBase);
}
}


@@ -182,33 +208,56 @@ status_t ImageCopy(C2GraphicView &view, const uint8_t *imgBase, const MediaImage
    int32_t dst_stride_v = view.layout().planes[2].rowInc;
    int32_t dst_stride_v = view.layout().planes[2].rowInc;
    int width = view.crop().width;
    int width = view.crop().width;
    int height = view.crop().height;
    int height = view.crop().height;
    if ((IsNV12(img) && IsI420(view)) || (IsI420(img) && IsNV12(view))) {
    if (IsNV12(img)) {
        // Take shortcuts to use libyuv functions between NV12 and I420 conversion.
        if (IsNV12(view)) {
        if (IsNV12(img) && IsI420(view)) {
            libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
            libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height / 2);
            return OK;
        } else if (IsNV21(view)) {
            if (!libyuv::NV21ToNV12(src_y, src_stride_y, src_u, src_stride_u,
                                    dst_y, dst_stride_y, dst_v, dst_stride_v, width, height)) {
                return OK;
            }
        } else if (IsI420(view)) {
            if (!libyuv::NV12ToI420(src_y, src_stride_y, src_u, src_stride_u, dst_y, dst_stride_y,
            if (!libyuv::NV12ToI420(src_y, src_stride_y, src_u, src_stride_u, dst_y, dst_stride_y,
                                    dst_u, dst_stride_u, dst_v, dst_stride_v, width, height)) {
                                    dst_u, dst_stride_u, dst_v, dst_stride_v, width, height)) {
                return OK;
                return OK;
            }
            }
        } else {
        }
            if (!libyuv::I420ToNV12(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
    } else if (IsNV21(img)) {
        if (IsNV12(view)) {
            if (!libyuv::NV21ToNV12(src_y, src_stride_y, src_v, src_stride_v,
                                    dst_y, dst_stride_y, dst_u, dst_stride_u, width, height)) {
                                    dst_y, dst_stride_y, dst_u, dst_stride_u, width, height)) {
                return OK;
                return OK;
            }
            }
        } else if (IsNV21(view)) {
            libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
            libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width, height / 2);
            return OK;
        } else if (IsI420(view)) {
            if (!libyuv::NV21ToI420(src_y, src_stride_y, src_v, src_stride_v, dst_y, dst_stride_y,
                                    dst_u, dst_stride_u, dst_v, dst_stride_v, width, height)) {
                return OK;
            }
            }
        }
        }
    if (IsNV12(img) && IsNV12(view)) {
    } else if (IsI420(img)) {
        // For NV12, copy Y and UV plane
        if (IsNV12(view)) {
        libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
            if (!libyuv::I420ToNV12(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
        libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height / 2);
                                    dst_y, dst_stride_y, dst_u, dst_stride_u, width, height)) {
                return OK;
            }
        } else if (IsNV21(view)) {
            if (!libyuv::I420ToNV21(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
                                    dst_y, dst_stride_y, dst_v, dst_stride_v, width, height)) {
                return OK;
                return OK;
            }
            }
    if (IsI420(img) && IsI420(view)) {
        } else if (IsI420(view)) {
        // For I420, copy Y, U and V plane.
            libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
            libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
            libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width / 2, height / 2);
            libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width / 2, height / 2);
            libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width / 2, height / 2);
            libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width / 2, height / 2);
            return OK;
            return OK;
        }
        }
    }
    return _ImageCopy<false>(view, img, imgBase);
    return _ImageCopy<false>(view, img, imgBase);
}
}


@@ -250,6 +299,20 @@ bool IsNV12(const C2GraphicView &view) {
            && layout.planes[layout.PLANE_V].offset == 1);
            && layout.planes[layout.PLANE_V].offset == 1);
}
}


bool IsNV21(const C2GraphicView &view) {
    if (!IsYUV420(view)) {
        return false;
    }
    const C2PlanarLayout &layout = view.layout();
    return (layout.rootPlanes == 2
            && layout.planes[layout.PLANE_U].colInc == 2
            && layout.planes[layout.PLANE_U].rootIx == layout.PLANE_V
            && layout.planes[layout.PLANE_U].offset == 1
            && layout.planes[layout.PLANE_V].colInc == 2
            && layout.planes[layout.PLANE_V].rootIx == layout.PLANE_V
            && layout.planes[layout.PLANE_V].offset == 0);
}

bool IsI420(const C2GraphicView &view) {
bool IsI420(const C2GraphicView &view) {
    if (!IsYUV420(view)) {
    if (!IsYUV420(view)) {
        return false;
        return false;
@@ -286,6 +349,15 @@ bool IsNV12(const MediaImage2 *img) {
            && (img->mPlane[2].mOffset - img->mPlane[1].mOffset == 1));
            && (img->mPlane[2].mOffset - img->mPlane[1].mOffset == 1));
}
}


bool IsNV21(const MediaImage2 *img) {
    if (!IsYUV420(img)) {
        return false;
    }
    return (img->mPlane[1].mColInc == 2
            && img->mPlane[2].mColInc == 2
            && (img->mPlane[1].mOffset - img->mPlane[2].mOffset == 1));
}

bool IsI420(const MediaImage2 *img) {
bool IsI420(const MediaImage2 *img) {
    if (!IsYUV420(img)) {
    if (!IsYUV420(img)) {
        return false;
        return false;
@@ -295,6 +367,76 @@ bool IsI420(const MediaImage2 *img) {
            && img->mPlane[2].mOffset > img->mPlane[1].mOffset);
            && img->mPlane[2].mOffset > img->mPlane[1].mOffset);
}
}


FlexLayout GetYuv420FlexibleLayout() {
    static FlexLayout sLayout = []{
        AHardwareBuffer_Desc desc = {
            16,  // width
            16,  // height
            1,   // layers
            AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420,
            AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
            0,   // stride
            0,   // rfu0
            0,   // rfu1
        };
        AHardwareBuffer *buffer = nullptr;
        int ret = AHardwareBuffer_allocate(&desc, &buffer);
        if (ret != 0) {
            return FLEX_LAYOUT_UNKNOWN;
        }
        class AutoCloser {
        public:
            AutoCloser(AHardwareBuffer *buffer) : mBuffer(buffer), mLocked(false) {}
            ~AutoCloser() {
                if (mLocked) {
                    AHardwareBuffer_unlock(mBuffer, nullptr);
                }
                AHardwareBuffer_release(mBuffer);
            }

            void setLocked() { mLocked = true; }

        private:
            AHardwareBuffer *mBuffer;
            bool mLocked;
        } autoCloser(buffer);
        AHardwareBuffer_Planes planes;
        ret = AHardwareBuffer_lockPlanes(
                buffer,
                AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
                -1,       // fence
                nullptr,  // rect
                &planes);
        if (ret != 0) {
            AHardwareBuffer_release(buffer);
            return FLEX_LAYOUT_UNKNOWN;
        }
        autoCloser.setLocked();
        if (planes.planeCount != 3) {
            return FLEX_LAYOUT_UNKNOWN;
        }
        if (planes.planes[0].pixelStride != 1) {
            return FLEX_LAYOUT_UNKNOWN;
        }
        if (planes.planes[1].pixelStride == 1 && planes.planes[2].pixelStride == 1) {
            return FLEX_LAYOUT_PLANAR;
        }
        if (planes.planes[1].pixelStride == 2 && planes.planes[2].pixelStride == 2) {
            ssize_t uvDist =
                static_cast<uint8_t *>(planes.planes[2].data) -
                static_cast<uint8_t *>(planes.planes[1].data);
            if (uvDist == 1) {
                return FLEX_LAYOUT_SEMIPLANAR_UV;
            } else if (uvDist == -1) {
                return FLEX_LAYOUT_SEMIPLANAR_VU;
            }
            return FLEX_LAYOUT_UNKNOWN;
        }
        return FLEX_LAYOUT_UNKNOWN;
    }();
    return sLayout;
}

MediaImage2 CreateYUV420PlanarMediaImage2(
MediaImage2 CreateYUV420PlanarMediaImage2(
        uint32_t width, uint32_t height, uint32_t stride, uint32_t vstride) {
        uint32_t width, uint32_t height, uint32_t stride, uint32_t vstride) {
    return MediaImage2 {
    return MediaImage2 {
+21 −0
Original line number Original line Diff line number Diff line
@@ -95,6 +95,11 @@ bool IsYUV420(const C2GraphicView &view);
 */
 */
bool IsNV12(const C2GraphicView &view);
bool IsNV12(const C2GraphicView &view);


/**
 * Returns true iff a view has a NV21 layout.
 */
bool IsNV21(const C2GraphicView &view);

/**
/**
 * Returns true iff a view has a I420 layout.
 * Returns true iff a view has a I420 layout.
 */
 */
@@ -110,11 +115,27 @@ bool IsYUV420(const MediaImage2 *img);
 */
 */
bool IsNV12(const MediaImage2 *img);
bool IsNV12(const MediaImage2 *img);


/**
 * Returns true iff a MediaImage2 has a NV21 layout.
 */
bool IsNV21(const MediaImage2 *img);

/**
/**
 * Returns true iff a MediaImage2 has a I420 layout.
 * Returns true iff a MediaImage2 has a I420 layout.
 */
 */
bool IsI420(const MediaImage2 *img);
bool IsI420(const MediaImage2 *img);


enum FlexLayout {
    FLEX_LAYOUT_UNKNOWN,
    FLEX_LAYOUT_PLANAR,
    FLEX_LAYOUT_SEMIPLANAR_UV,
    FLEX_LAYOUT_SEMIPLANAR_VU,
};
/**
 * Returns layout of YCBCR_420_888 pixel format.
 */
FlexLayout GetYuv420FlexibleLayout();

/**
/**
 * A raw memory block to use for internal buffers.
 * A raw memory block to use for internal buffers.
 *
 *