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

Commit 2af532de authored by Harish Mahendrakar's avatar Harish Mahendrakar Committed by Cherrypicker Worker
Browse files

C2SoftDav1dDec: Move libyuv calls to SimpleC2Component

libyuv calls are now moved to functions in SimpleC2Component, so that
they can be called from other plugins as well in the future.

Also, with this libcodec2_soft_av1dec_dav1d.so doesn't depend on libyuv
directly and instead libcodec2_soft_common.so depends on libyuv.

This helps in handling cfi related failures that are seen when some
*.so declared cfi_assembly_support as true and some didn't and had a
depedency on libyuv.

Bug: 286058440
Bug: 286564165

Test: stagefright -s av1.webm
(cherry picked from https://android-review.googlesource.com/q/commit:29351ea15cff8f08af4f0b3085eb2bad71cdb72c)
Merged-In: I230227149cffe45a8cc47fe1095685af1e95fc34
Change-Id: I230227149cffe45a8cc47fe1095685af1e95fc34
parent 09e6c9f7
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -42,6 +42,10 @@ cc_library {
        "libnativewindow_headers",
    ],

    static_libs: [
        "libyuv_static", // for conversion routines
    ],

    shared_libs: [
        "libcutils", // for properties
        "liblog", // for ALOG
+125 −0
Original line number Diff line number Diff line
@@ -21,8 +21,10 @@
#include <android/hardware_buffer.h>
#include <cutils/properties.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>

#include <inttypes.h>
#include <libyuv.h>

#include <C2Config.h>
#include <C2Debug.h>
@@ -32,6 +34,15 @@
#include <SimpleC2Component.h>

namespace android {

// libyuv version required for I410ToAB30Matrix and I210ToAB30Matrix.
#if LIBYUV_VERSION >= 1780
#include <algorithm>
#define HAVE_LIBYUV_I410_I210_TO_AB30 1
#else
#define HAVE_LIBYUV_I410_I210_TO_AB30 0
#endif

constexpr uint8_t kNeutralUVBitDepth8 = 128;
constexpr uint16_t kNeutralUVBitDepth10 = 512;

@@ -506,6 +517,120 @@ void convertRGBA1010102ToYUV420Planar16(uint16_t* dstY, uint16_t* dstU, uint16_t
    }
}

void convertPlanar16ToY410OrRGBA1010102(uint8_t* dst, const uint16_t* srcY, const uint16_t* srcU,
                                        const uint16_t* srcV, size_t srcYStride, size_t srcUStride,
                                        size_t srcVStride, size_t dstStride, size_t width,
                                        size_t height,
                                        std::shared_ptr<const C2ColorAspectsStruct> aspects,
                                        CONV_FORMAT_T format) {
    bool processed = false;
#if HAVE_LIBYUV_I410_I210_TO_AB30
    if (format == CONV_FORMAT_I444) {
        libyuv::I410ToAB30Matrix(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dst,
                                 dstStride, &libyuv::kYuvV2020Constants, width, height);
        processed = true;
    } else if (format == CONV_FORMAT_I422) {
        libyuv::I210ToAB30Matrix(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dst,
                                 dstStride, &libyuv::kYuvV2020Constants, width, height);
        processed = true;
    }
#endif  // HAVE_LIBYUV_I410_I210_TO_AB30
    if (!processed) {
        convertYUV420Planar16ToY410OrRGBA1010102(
                (uint32_t*)dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
                dstStride / sizeof(uint32_t), width, height,
                std::static_pointer_cast<const C2ColorAspectsStruct>(aspects));
    }
}

void convertPlanar16ToP010(uint16_t* dstY, uint16_t* dstUV, const uint16_t* srcY,
                           const uint16_t* srcU, const uint16_t* srcV, size_t srcYStride,
                           size_t srcUStride, size_t srcVStride, size_t dstYStride,
                           size_t dstUStride, size_t dstVStride, size_t width, size_t height,
                           bool isMonochrome, CONV_FORMAT_T format, uint16_t* tmpFrameBuffer,
                           size_t tmpFrameBufferSize) {
#if LIBYUV_VERSION >= 1779
    if ((format == CONV_FORMAT_I444) || (format == CONV_FORMAT_I422)) {
        // TODO(https://crbug.com/libyuv/952): replace this block with libyuv::I410ToP010
        // and libyuv::I210ToP010 when they are available. Note it may be safe to alias dstY
        // in I010ToP010, but the libyuv API doesn't make any guarantees.
        const size_t tmpSize = dstYStride * height + dstUStride * align(height, 2);
        CHECK(tmpSize <= tmpFrameBufferSize);

        uint16_t* const tmpY = tmpFrameBuffer;
        uint16_t* const tmpU = tmpY + dstYStride * height;
        uint16_t* const tmpV = tmpU + dstUStride * align(height, 2) / 2;
        if (format == CONV_FORMAT_I444) {
            libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY,
                               dstYStride, tmpU, dstUStride, tmpV, dstUStride, width, height);
        } else {
            libyuv::I210ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY,
                               dstYStride, tmpU, dstUStride, tmpV, dstUStride, width, height);
        }
        libyuv::I010ToP010(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstVStride, dstY, dstYStride,
                           dstUV, dstUStride, width, height);
    } else {
        convertYUV420Planar16ToP010(dstY, dstUV, srcY, srcU, srcV, srcYStride, srcUStride,
                                    srcVStride, dstYStride, dstUStride, width, height,
                                    isMonochrome);
    }
#else   // LIBYUV_VERSION < 1779
    convertYUV420Planar16ToP010(dstY, dstUV, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
                                dstYStride, dstUStride, width, height, isMonochrome);
#endif  // LIBYUV_VERSION >= 1779
}

void convertPlanar16ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uint16_t* srcY,
                           const uint16_t* srcU, const uint16_t* srcV, size_t srcYStride,
                           size_t srcUStride, size_t srcVStride, size_t dstYStride,
                           size_t dstUStride, size_t dstVStride, size_t width, size_t height,
                           bool isMonochrome, CONV_FORMAT_T format, uint16_t* tmpFrameBuffer,
                           size_t tmpFrameBufferSize) {
#if LIBYUV_VERSION >= 1779
    if (format == CONV_FORMAT_I444) {
        // TODO(https://crbug.com/libyuv/950): replace this block with libyuv::I410ToI420
        // when it's available.
        const size_t tmpSize = dstYStride * height + dstUStride * align(height, 2);
        CHECK(tmpSize <= tmpFrameBufferSize);

        uint16_t* const tmpY = tmpFrameBuffer;
        uint16_t* const tmpU = tmpY + dstYStride * height;
        uint16_t* const tmpV = tmpU + dstUStride * align(height, 2) / 2;
        libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY, dstYStride,
                           tmpU, dstUStride, tmpV, dstVStride, width, height);
        libyuv::I010ToI420(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride, dstY, dstYStride,
                           dstU, dstUStride, dstV, dstVStride, width, height);
    } else if (format == CONV_FORMAT_I422) {
        libyuv::I210ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY, dstYStride,
                           dstU, dstUStride, dstV, dstVStride, width, height);
    } else {
        convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
                                    srcVStride, dstYStride, dstUStride, width, height,
                                    isMonochrome);
    }
#else   // LIBYUV_VERSION < 1779
    convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
                                srcVStride, dstYStride, dstUStride, width, height, isMonochrome);
#endif  // LIBYUV_VERSION >= 1779
}

void convertPlanar8ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uint8_t* srcY,
                          const uint8_t* srcU, const uint8_t* srcV, size_t srcYStride,
                          size_t srcUStride, size_t srcVStride, size_t dstYStride,
                          size_t dstUStride, size_t dstVStride, uint32_t width, uint32_t height,
                          bool isMonochrome, CONV_FORMAT_T format) {
    if (format == CONV_FORMAT_I444) {
        libyuv::I444ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY, dstYStride,
                           dstU, dstUStride, dstV, dstVStride, width, height);
    } else if (format == CONV_FORMAT_I422) {
        libyuv::I422ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY, dstYStride,
                           dstU, dstUStride, dstV, dstVStride, width, height);
    } else {
        convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
                                   srcVStride, dstYStride, dstUStride, dstVStride, width, height,
                                   isMonochrome);
    }
}
std::unique_ptr<C2Work> SimpleC2Component::WorkQueue::pop_front() {
    std::unique_ptr<C2Work> work = std::move(mQueue.front().work);
    mQueue.pop_front();
+30 −0
Original line number Diff line number Diff line
@@ -31,6 +31,12 @@ struct C2ColorAspectsStruct;

namespace android {

typedef enum {
    CONV_FORMAT_I420,
    CONV_FORMAT_I422,
    CONV_FORMAT_I444,
} CONV_FORMAT_T;

void convertYUV420Planar8ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint8_t *srcY,
                                const uint8_t *srcU, const uint8_t *srcV, size_t srcYStride,
                                size_t srcUStride, size_t srcVStride, size_t dstYStride,
@@ -66,6 +72,30 @@ void convertRGBA1010102ToYUV420Planar16(uint16_t* dstY, uint16_t* dstU, uint16_t
                                        const uint32_t* srcRGBA, size_t srcRGBStride, size_t width,
                                        size_t height, C2Color::matrix_t colorMatrix,
                                        C2Color::range_t colorRange);
void convertPlanar16ToY410OrRGBA1010102(uint8_t* dst, const uint16_t* srcY, const uint16_t* srcU,
                                        const uint16_t* srcV, size_t srcYStride, size_t srcUStride,
                                        size_t srcVStride, size_t dstStride, size_t width,
                                        size_t height,
                                        std::shared_ptr<const C2ColorAspectsStruct> aspects,
                                        CONV_FORMAT_T format);

void convertPlanar16ToP010(uint16_t* dstY, uint16_t* dstUV, const uint16_t* srcY,
                           const uint16_t* srcU, const uint16_t* srcV, size_t srcYStride,
                           size_t srcUStride, size_t srcVStride, size_t dstYStride,
                           size_t dstUStride, size_t dstVStride, size_t width, size_t height,
                           bool isMonochrome, CONV_FORMAT_T format, uint16_t* tmpFrameBuffer,
                           size_t tmpFrameBufferSize);
void convertPlanar16ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uint16_t* srcY,
                           const uint16_t* srcU, const uint16_t* srcV, size_t srcYStride,
                           size_t srcUStride, size_t srcVStride, size_t dstYStride,
                           size_t dstUStride, size_t dstVStride, size_t width, size_t height,
                           bool isMonochrome, CONV_FORMAT_T format, uint16_t* tmpFrameBuffer,
                           size_t tmpFrameBufferSize);
void convertPlanar8ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uint8_t* srcY,
                          const uint8_t* srcU, const uint8_t* srcV, size_t srcYStride,
                          size_t srcUStride, size_t srcVStride, size_t dstYStride,
                          size_t dstUStride, size_t dstVStride, uint32_t width, uint32_t height,
                          bool isMonochrome, CONV_FORMAT_T format);

class SimpleC2Component
        : public C2Component, public std::enable_shared_from_this<SimpleC2Component> {
+1 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ cc_library {
    defaults: [
        "libcodec2_soft-defaults",
        "libcodec2_soft_sanitize_all-defaults",
        "libcodec2_soft_sanitize_cfi-defaults",
    ],

    cflags: [
@@ -24,7 +25,6 @@ cc_library {

    srcs: ["C2SoftDav1dDec.cpp"],
    static_libs: [
        "libyuv_static",
        "libdav1d_8bit",
        "libdav1d_16bit",
    ],
+44 −123
Original line number Diff line number Diff line
@@ -26,20 +26,11 @@
#include <Codec2CommonUtils.h>
#include <Codec2Mapper.h>
#include <SimpleC2Interface.h>
#include <libyuv.h>
#include <log/log.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/foundation/MediaDefs.h>
#include "C2SoftDav1dDec.h"

// libyuv version required for I410ToAB30Matrix and I210ToAB30Matrix.
#if LIBYUV_VERSION >= 1780
#include <algorithm>
#define HAVE_LIBYUV_I410_I210_TO_AB30 1
#else
#define HAVE_LIBYUV_I410_I210_TO_AB30 0
#endif

namespace android {

// Flag to enable dumping the bitsteram and the decoded pictures to files.
@@ -1114,16 +1105,6 @@ bool C2SoftDav1dDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
    // out_frameIndex that the decoded picture returns from dav1d.
    int64_t out_frameIndex = img.m.timestamp;

#if LIBYUV_VERSION < 1779
    if (!(img.p.layout != DAV1D_PIXEL_LAYOUT_I400 || img.p.layout != DAV1D_PIXEL_LAYOUT_I420)) {
        ALOGE("image_format %d not supported", img.p.layout);
        mSignalledError = true;
        work->workletsProcessed = 1u;
        work->result = C2_CORRUPTED;
        return false;
    }
#endif

    const bool isMonochrome = img.p.layout == DAV1D_PIXEL_LAYOUT_I400;

    int bitdepth = img.p.bpc;
@@ -1141,17 +1122,6 @@ bool C2SoftDav1dDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
            allowRGBA1010102 = true;
        }
        format = getHalPixelFormatForBitDepth10(allowRGBA1010102);
#if !HAVE_LIBYUV_I410_I210_TO_AB30
        if ((format == HAL_PIXEL_FORMAT_RGBA_1010102) &&
            (is_img_ready ? img.p.layout == DAV1D_PIXEL_LAYOUT_I420
                          : buffer->image_format != libgav1::kImageFormatYuv420)) {
            ALOGE("Only YUV420 output is supported when targeting RGBA_1010102");
            mSignalledError = true;
            work->result = C2_OMITTED;
            work->workletsProcessed = 1u;
            return false;
        }
#endif
    }

    if (mHalPixelFormat != format) {
@@ -1206,6 +1176,19 @@ bool C2SoftDav1dDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
    size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
    size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;

    CONV_FORMAT_T convFormat;
    switch (img.p.layout) {
        case DAV1D_PIXEL_LAYOUT_I444:
            convFormat = CONV_FORMAT_I444;
            break;
        case DAV1D_PIXEL_LAYOUT_I422:
            convFormat = CONV_FORMAT_I422;
            break;
        default:
            convFormat = CONV_FORMAT_I420;
            break;
    }

    if (bitdepth == 10) {
        // TODO: b/277797541 - Investigate if we can ask DAV1D to output the required format during
        // decompression to avoid color conversion.
@@ -1217,19 +1200,6 @@ bool C2SoftDav1dDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
        size_t srcVStride = img.stride[1] / 2;

        if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
            bool processed = false;
#if HAVE_LIBYUV_I410_I210_TO_AB30
            if (img.p.layout == DAV1D_PIXEL_LAYOUT_I444) {
                libyuv::I410ToAB30Matrix(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
                                         dstYStride, &libyuv::kYuvV2020Constants, mWidth, mHeight);
                processed = true;
            } else if (img.p.layout == DAV1D_PIXEL_LAYOUT_I422) {
                libyuv::I210ToAB30Matrix(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
                                         dstYStride, &libyuv::kYuvV2020Constants, mWidth, mHeight);
                processed = true;
            }
#endif  // HAVE_LIBYUV_I410_I210_TO_AB30
            if (!processed) {
            if (isMonochrome) {
                const size_t tmpSize = mWidth;
                const bool needFill = tmpSize > mTmpFrameBufferSize;
@@ -1244,83 +1214,42 @@ bool C2SoftDav1dDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
                    std::fill_n(mTmpFrameBuffer.get(), tmpSize, 512);
                }
            }
                convertYUV420Planar16ToY410OrRGBA1010102(
                        (uint32_t*)dstY, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
                        dstYStride / sizeof(uint32_t), mWidth, mHeight,
                        std::static_pointer_cast<const C2ColorAspectsStruct>(codedColorAspects));
            }
            convertPlanar16ToY410OrRGBA1010102(
                    dstY, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
                    dstYStride, mWidth, mHeight,
                    std::static_pointer_cast<const C2ColorAspectsStruct>(codedColorAspects),
                    convFormat);
        } else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
            dstYStride /= 2;
            dstUStride /= 2;
            dstVStride /= 2;
#if LIBYUV_VERSION >= 1779
            size_t tmpSize = 0;
            if ((img.p.layout == DAV1D_PIXEL_LAYOUT_I444) ||
                (img.p.layout == DAV1D_PIXEL_LAYOUT_I422)) {
                // TODO(https://crbug.com/libyuv/952): replace this block with libyuv::I410ToP010
                // and libyuv::I210ToP010 when they are available. Note it may be safe to alias dstY
                // in I010ToP010, but the libyuv API doesn't make any guarantees.
                const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
                tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
                if (!allocTmpFrameBuffer(tmpSize)) {
                    ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
                    setError(work, C2_NO_MEMORY);
                    return false;
                }
                uint16_t* const tmpY = mTmpFrameBuffer.get();
                uint16_t* const tmpU = tmpY + dstYStride * mHeight;
                uint16_t* const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
                if (img.p.layout == DAV1D_PIXEL_LAYOUT_I444) {
                    libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY,
                                       dstYStride, tmpU, dstUStride, tmpV, dstUStride, mWidth,
                                       mHeight);
                } else {
                    libyuv::I210ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY,
                                       dstYStride, tmpU, dstUStride, tmpV, dstUStride, mWidth,
                                       mHeight);
            }
                libyuv::I010ToP010(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstVStride,
                                   (uint16_t*)dstY, dstYStride, (uint16_t*)dstU, dstUStride, mWidth,
                                   mHeight);
            convertPlanar16ToP010((uint16_t*)dstY, (uint16_t*)dstU, srcY, srcU, srcV, srcYStride,
                                  srcUStride, srcVStride, dstYStride, dstUStride, dstVStride,
                                  mWidth, mHeight, isMonochrome, convFormat, mTmpFrameBuffer.get(),
                                  tmpSize);
        } else {
                convertYUV420Planar16ToP010((uint16_t*)dstY, (uint16_t*)dstU, srcY, srcU, srcV,
                                            srcYStride, srcUStride, srcVStride, dstYStride,
                                            dstUStride, mWidth, mHeight, isMonochrome);
            }
#else   // LIBYUV_VERSION < 1779
            convertYUV420Planar16ToP010((uint16_t*)dstY, (uint16_t*)dstU, srcY, srcU, srcV,
                                        srcYStride, srcUStride, srcVStride, dstYStride, dstUStride,
                                        mWidth, mHeight, isMonochrome);
#endif  // LIBYUV_VERSION >= 1779
        } else {
#if LIBYUV_VERSION >= 1779
            size_t tmpSize = 0;
            if (img.p.layout == DAV1D_PIXEL_LAYOUT_I444) {
                // TODO(https://crbug.com/libyuv/950): replace this block with libyuv::I410ToI420
                // when it's available.
                const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
                tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
                if (!allocTmpFrameBuffer(tmpSize)) {
                    ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
                    setError(work, C2_NO_MEMORY);
                    return false;
                }
                uint16_t* const tmpY = mTmpFrameBuffer.get();
                uint16_t* const tmpU = tmpY + dstYStride * mHeight;
                uint16_t* const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
                libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY,
                                   dstYStride, tmpU, dstUStride, tmpV, dstVStride, mWidth, mHeight);
                libyuv::I010ToI420(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride, dstY,
                                   dstYStride, dstU, dstUStride, dstV, dstVStride, mWidth, mHeight);
            } else if (img.p.layout == DAV1D_PIXEL_LAYOUT_I422) {
                libyuv::I210ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
                                   dstYStride, dstU, dstUStride, dstV, dstVStride, mWidth, mHeight);
            } else {
                convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride,
                                            srcUStride, srcVStride, dstYStride, dstUStride, mWidth,
                                            mHeight, isMonochrome);
            }
#else   // LIBYUV_VERSION < 1779
            convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
                                        srcVStride, dstYStride, dstUStride, mWidth, mHeight,
                                        isMonochrome);
#endif  // LIBYUV_VERSION >= 1779
            convertPlanar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
                                  srcVStride, dstYStride, dstUStride, dstVStride, mWidth, mHeight,
                                  isMonochrome, convFormat, mTmpFrameBuffer.get(), tmpSize);
        }

        // Dump the output buffer if dumping is enabled (debug only).
@@ -1401,17 +1330,9 @@ bool C2SoftDav1dDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
            }
        }
#endif
        if (img.p.layout == DAV1D_PIXEL_LAYOUT_I444) {
            libyuv::I444ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
                               dstYStride, dstU, dstUStride, dstV, dstVStride, mWidth, mHeight);
        } else if (img.p.layout == DAV1D_PIXEL_LAYOUT_I422) {
            libyuv::I422ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
                               dstYStride, dstU, dstUStride, dstV, dstVStride, mWidth, mHeight);
        } else {
            convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
                                       srcVStride, dstYStride, dstUStride, dstVStride, mWidth,
                                       mHeight, isMonochrome);
        }
        convertPlanar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
                             dstYStride, dstUStride, dstVStride, mWidth, mHeight, isMonochrome,
                             convFormat);
    }

    dav1d_picture_unref(&img);