static int planarCopyWrapper(SwsContext *c, const uint8_t *src[],

                             int srcStride[], int srcSliceY, int srcSliceH,

                             uint8_t *dst[], int dstStride[])

{

    const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);

    const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);

    int plane, i, j;

    for (plane = 0; plane < 4; plane++) {

        int length = (plane == 0 || plane == 3) ? c->srcW  : -((-c->srcW  ) >> c->chrDstHSubSample);

        int y =      (plane == 0 || plane == 3) ? srcSliceY: -((-srcSliceY) >> c->chrDstVSubSample);

        int height = (plane == 0 || plane == 3) ? srcSliceH: -((-srcSliceH) >> c->chrDstVSubSample);

        const uint8_t *srcPtr = src[plane];

        uint8_t *dstPtr = dst[plane] + dstStride[plane] * y;



        if (!dst[plane])

            continue;

        // ignore palette for GRAY8

        if (plane == 1 && !dst[2]) continue;

        if (!src[plane] || (plane == 1 && !src[2])) {

            int val = (plane == 3) ? 255 : 128;

            if (is16BPS(c->dstFormat))

                length *= 2;

            if (is9_OR_10BPS(c->dstFormat)) {

                fill_plane9or10(dst[plane], dstStride[plane],

                                length, height, y, val,

                                desc_dst->comp[plane].depth_minus1 + 1,

                                isBE(c->dstFormat));

            } else

                fillPlane(dst[plane], dstStride[plane], length, height, y,

                          val);

        } else {

            if (is9_OR_10BPS(c->srcFormat)) {

                const int src_depth = desc_src->comp[plane].depth_minus1 + 1;

                const int dst_depth = desc_dst->comp[plane].depth_minus1 + 1;

                const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;



                if (is16BPS(c->dstFormat)) {

                    uint16_t *dstPtr2 = (uint16_t *) dstPtr;

#define COPY9_OR_10TO16(rfunc, wfunc) \

                    for (i = 0; i < height; i++) { \

                        for (j = 0; j < length; j++) { \

                            int srcpx = rfunc(&srcPtr2[j]); \

                            wfunc(&dstPtr2[j], (srcpx << (16 - src_depth)) | (srcpx >> (2 * src_depth - 16))); \

                        } \

                        dstPtr2 += dstStride[plane] / 2; \

                        srcPtr2 += srcStride[plane] / 2; \

                    }

                    if (isBE(c->dstFormat)) {

                        if (isBE(c->srcFormat)) {

                            COPY9_OR_10TO16(AV_RB16, AV_WB16);

                        } else {

                            COPY9_OR_10TO16(AV_RL16, AV_WB16);

                        }

                    } else {

                        if (isBE(c->srcFormat)) {

                            COPY9_OR_10TO16(AV_RB16, AV_WL16);

                        } else {

                            COPY9_OR_10TO16(AV_RL16, AV_WL16);

                        }

                    }

                } else if (is9_OR_10BPS(c->dstFormat)) {

                    uint16_t *dstPtr2 = (uint16_t *) dstPtr;

#define COPY9_OR_10TO9_OR_10(loop) \

                    for (i = 0; i < height; i++) { \

                        for (j = 0; j < length; j++) { \

                            loop; \

                        } \

                        dstPtr2 += dstStride[plane] / 2; \

                        srcPtr2 += srcStride[plane] / 2; \

                    }

#define COPY9_OR_10TO9_OR_10_2(rfunc, wfunc) \

                    if (dst_depth > src_depth) { \

                        COPY9_OR_10TO9_OR_10(int srcpx = rfunc(&srcPtr2[j]); \

                            wfunc(&dstPtr2[j], (srcpx << 1) | (srcpx >> 9))); \

                    } else if (dst_depth < src_depth) { \

                        DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \

                                    srcPtr2, srcStride[plane] / 2, rfunc, \

                                    dither_8x8_1, 1, clip9); \

                    } else { \

                        COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]))); \

                    }

                    if (isBE(c->dstFormat)) {

                        if (isBE(c->srcFormat)) {

                            COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WB16);

                        } else {

                            COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WB16);

                        }

                    } else {

                        if (isBE(c->srcFormat)) {

                            COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WL16);

                        } else {

                            COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WL16);

                        }

                    }

                } else {

#define W8(a, b) { *(a) = (b); }

#define COPY9_OR_10TO8(rfunc) \

                    if (src_depth == 9) { \

                        DITHER_COPY(dstPtr,  dstStride[plane],   W8, \

                                    srcPtr2, srcStride[plane] / 2, rfunc, \

                                    dither_8x8_1, 1, av_clip_uint8); \

                    } else { \

                        DITHER_COPY(dstPtr,  dstStride[plane],   W8, \

                                    srcPtr2, srcStride[plane] / 2, rfunc, \

                                    dither_8x8_3, 2, av_clip_uint8); \

                    }

                    if (isBE(c->srcFormat)) {

                        COPY9_OR_10TO8(AV_RB16);

                    } else {

                        COPY9_OR_10TO8(AV_RL16);

                    }

                }

            } else if (is9_OR_10BPS(c->dstFormat)) {

                const int dst_depth = desc_dst->comp[plane].depth_minus1 + 1;

                uint16_t *dstPtr2 = (uint16_t *) dstPtr;



                if (is16BPS(c->srcFormat)) {

                    const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;

#define COPY16TO9_OR_10(rfunc, wfunc) \

                    if (dst_depth == 9) { \

                        DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \

                                    srcPtr2, srcStride[plane] / 2, rfunc, \

                                    ff_dither_8x8_128, 7, clip9); \

                    } else { \

                        DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \

                                    srcPtr2, srcStride[plane] / 2, rfunc, \

                                    dither_8x8_64, 6, clip10); \

                    }

                    if (isBE(c->dstFormat)) {

                        if (isBE(c->srcFormat)) {

                            COPY16TO9_OR_10(AV_RB16, AV_WB16);

                        } else {

                            COPY16TO9_OR_10(AV_RL16, AV_WB16);

                        }

                    } else {

                        if (isBE(c->srcFormat)) {

                            COPY16TO9_OR_10(AV_RB16, AV_WL16);

                        } else {

                            COPY16TO9_OR_10(AV_RL16, AV_WL16);

                        }

                    }

                } else /* 8bit */ {

#define COPY8TO9_OR_10(wfunc) \

                    for (i = 0; i < height; i++) { \

                        for (j = 0; j < length; j++) { \

                            const int srcpx = srcPtr[j]; \

                            wfunc(&dstPtr2[j], (srcpx << (dst_depth - 8)) | (srcpx >> (16 - dst_depth))); \

                        } \

                        dstPtr2 += dstStride[plane] / 2; \

                        srcPtr  += srcStride[plane]; \

                    }

                    if (isBE(c->dstFormat)) {

                        COPY8TO9_OR_10(AV_WB16);

                    } else {

                        COPY8TO9_OR_10(AV_WL16);

                    }

                }

            } else if (is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) {

                const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;

#define COPY16TO8(rfunc) \

                    DITHER_COPY(dstPtr,  dstStride[plane],   W8, \

                                srcPtr2, srcStride[plane] / 2, rfunc, \

                                dither_8x8_256, 8, av_clip_uint8);

                if (isBE(c->srcFormat)) {

                    COPY16TO8(AV_RB16);

                } else {

                    COPY16TO8(AV_RL16);

                }

            } else if (!is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) {

                for (i = 0; i < height; i++) {

                    for (j = 0; j < length; j++) {

                        dstPtr[ j << 1     ] = srcPtr[j];

                        dstPtr[(j << 1) + 1] = srcPtr[j];

                    }

                    srcPtr += srcStride[plane];

                    dstPtr += dstStride[plane];

                }

            } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) &&

                      isBE(c->srcFormat) != isBE(c->dstFormat)) {



                for (i = 0; i < height; i++) {

                    for (j = 0; j < length; j++)

                        ((uint16_t *) dstPtr)[j] = av_bswap16(((const uint16_t *) srcPtr)[j]);

                    srcPtr += srcStride[plane];

                    dstPtr += dstStride[plane];

                }

            } else if (dstStride[plane] == srcStride[plane] &&

                       srcStride[plane] > 0 && srcStride[plane] == length) {

                memcpy(dst[plane] + dstStride[plane] * y, src[plane],

                       height * dstStride[plane]);

            } else {

                if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat))

                    length *= 2;

                else if (!desc_src->comp[0].depth_minus1)

                    length >>= 3; // monowhite/black

                for (i = 0; i < height; i++) {

                    memcpy(dstPtr, srcPtr, length);

                    srcPtr += srcStride[plane];

                    dstPtr += dstStride[plane];

                }

            }

        }

    }

    return srcSliceH;

}
